diff --git a/BUILD.gn b/BUILD.gn index 9a4f5161..43149c93 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -123,9 +123,9 @@ } else { deps += [ "//courgette(//build/toolchain/win:x64)" ] } - if (is_chrome_branded) { - deps += [ "//remoting/host:remoting_host_installation" ] - } + } + if (is_chrome_branded) { + deps += [ "//remoting/host:remoting_host_installation" ] } }
diff --git a/DEPS b/DEPS index 39509e7..c0ceef72 100644 --- a/DEPS +++ b/DEPS
@@ -39,11 +39,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'a634b742320ae1c14ddb296e45569947daced9fc', + 'skia_revision': '703cf5aa20aaf01476f99299ca70a7e8b7aab4c5', # 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': 'ec7987147a99c0102a282559cd18a4a6b75d8a5c', + 'v8_revision': '24369bebbb3473baf0b03fa05cb0a80ab80de0d2', # 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. @@ -63,7 +63,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': 'd66f9d0b1fb0af57960f9c7163c475968505ee4a', + 'pdfium_revision': '1d023881cd53485303c0fcc0b5878e700dc470fd', # 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. @@ -71,7 +71,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. - 'boringssl_revision': '0d81373f9169637ff935449227be924c08bf1ec5', + 'boringssl_revision': '1991af69006a8fe4faf9b80b2340688846e62514', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling google-toolbox-for-mac # and whatever else without interference from each other. @@ -87,7 +87,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling NaCl # and whatever else without interference from each other. - 'nacl_revision': 'fe5bd51f9b79d27b2a3884181d4004cfccf70759', + 'nacl_revision': 'be714d07cf63b5e59921348fa1d2a5e9dc3059e5', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype-android # and whatever else without interference from each other. @@ -95,7 +95,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': 'e310b666b43f0ac98d4c9c46e0e9df3569ef69aa', + 'catapult_revision': 'c73d4a17b02306c5f05f71b4101b0b0c5a18a7f2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -114,7 +114,7 @@ deps = { 'src/breakpad/src': - Var('chromium_git') + '/breakpad/breakpad/src.git' + '@' + 'c85196f3c42b2eb8559464892a4b1749620a64d4', + Var('chromium_git') + '/breakpad/breakpad/src.git' + '@' + '0e618edbe53593064efd4bfd9316d77731bdc593', 'src/buildtools': Var('chromium_git') + '/chromium/buildtools.git' + '@' + Var('buildtools_revision'), @@ -350,7 +350,7 @@ Var('chromium_git') + '/external/github.com/swisspol/GCDWebServer.git' + '@' + '3d5fd0b8281a7224c057deb2d17709b5bea64836', 'src/ios/third_party/material_text_accessibility_ios/src': - Var('chromium_git') + '/external/github.com/google/material-text-accessibility-ios.git' + '@' + '5a8cb31cf26d661f4b0f5fbcc9119cf3930ed098', + Var('chromium_git') + '/external/github.com/google/material-text-accessibility-ios.git' + '@' + '96d2b0f13976a897bc7a41daf67f36d9548cff94', 'src/ios/third_party/ochamcrest/src': Var('chromium_git') + '/external/github.com/hamcrest/OCHamcrest.git' + '@' + 'd7ee4ecfb6bd13c3c8d364682b6228ccd86e1e1a',
diff --git a/android_webview/native/aw_contents_client_bridge.cc b/android_webview/native/aw_contents_client_bridge.cc index fa42019..04c3eea 100644 --- a/android_webview/native/aw_contents_client_bridge.cc +++ b/android_webview/native/aw_contents_client_bridge.cc
@@ -242,7 +242,7 @@ // Create an SSLPrivateKey wrapper for the private key JNI reference. scoped_refptr<net::SSLPrivateKey> private_key = - net::WrapJavaPrivateKey(private_key_ref); + net::WrapJavaPrivateKey(client_cert.get(), private_key_ref); if (!private_key) { LOG(ERROR) << "Could not create OpenSSL wrapper for private key"; return;
diff --git a/android_webview/native/permission/media_access_permission_request_unittest.cc b/android_webview/native/permission/media_access_permission_request_unittest.cc index eae252b..a34f6f9a 100644 --- a/android_webview/native/permission/media_access_permission_request_unittest.cc +++ b/android_webview/native/permission/media_access_permission_request_unittest.cc
@@ -53,7 +53,7 @@ content::MediaStreamRequest request( 0, 0, 0, origin, false, content::MEDIA_GENERATE_STREAM, audio_id, video_id, content::MEDIA_DEVICE_AUDIO_CAPTURE, - content::MEDIA_DEVICE_VIDEO_CAPTURE); + content::MEDIA_DEVICE_VIDEO_CAPTURE, false /* disable_local_echo */); std::unique_ptr<TestMediaAccessPermissionRequest> permission_request; permission_request.reset(new TestMediaAccessPermissionRequest(
diff --git a/ash/accelerators/accelerator_controller_delegate_aura.cc b/ash/accelerators/accelerator_controller_delegate_aura.cc index b0795d9..ede62ee 100644 --- a/ash/accelerators/accelerator_controller_delegate_aura.cc +++ b/ash/accelerators/accelerator_controller_delegate_aura.cc
@@ -357,7 +357,6 @@ #if defined(OS_CHROMEOS) case DEV_ADD_REMOVE_DISPLAY: case DEV_TOGGLE_UNIFIED_DESKTOP: - case TOGGLE_MIRROR_MODE: return debug::DeveloperAcceleratorsEnabled(); case SWAP_PRIMARY_DISPLAY: @@ -371,6 +370,7 @@ case LOCK_RELEASED: case POWER_PRESSED: case POWER_RELEASED: + case TOGGLE_MIRROR_MODE: case TOUCH_HUD_PROJECTION_TOGGLE: return true; #endif
diff --git a/ash/common/system/chromeos/palette/common_palette_tool.cc b/ash/common/system/chromeos/palette/common_palette_tool.cc index 7ea9f30f..e8061a19 100644 --- a/ash/common/system/chromeos/palette/common_palette_tool.cc +++ b/ash/common/system/chromeos/palette/common_palette_tool.cc
@@ -19,10 +19,18 @@ #include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/vector_icons_public.h" #include "ui/views/border.h" +#include "ui/views/controls/label.h" namespace ash { namespace { +// Returns the font used by any displayed labels. +const gfx::FontList& GetLabelFont() { + // TODO(tdanderson|jdufault): Use TrayPopupItemStyle instead. + return ui::ResourceBundle::GetSharedInstance().GetFontListWithDelta( + 1, gfx::Font::FontStyle::NORMAL, gfx::Font::Weight::MEDIUM); +} + void AddHistogramTimes(PaletteToolId id, base::TimeDelta duration) { if (id == PaletteToolId::LASER_POINTER) { UMA_HISTOGRAM_CUSTOM_TIMES("Ash.Shelf.Palette.InLaserPointerMode", duration, @@ -42,12 +50,6 @@ CommonPaletteTool::~CommonPaletteTool() {} -views::View* CommonPaletteTool::CreateView() { - // TODO(jdufault): Use real strings. - return CreateDefaultView( - base::ASCIIToUTF16("[TODO] " + PaletteToolIdToString(GetToolId()))); -} - void CommonPaletteTool::OnViewDestroyed() { highlight_view_ = nullptr; } @@ -56,20 +58,16 @@ PaletteTool::OnEnable(); start_time_ = base::TimeTicks::Now(); - if (highlight_view_) { - highlight_view_->SetHighlight(true); + if (highlight_view_) highlight_view_->SetRightIconVisible(true); - } } void CommonPaletteTool::OnDisable() { PaletteTool::OnDisable(); AddHistogramTimes(GetToolId(), base::TimeTicks::Now() - start_time_); - if (highlight_view_) { - highlight_view_->SetHighlight(false); + if (highlight_view_) highlight_view_->SetRightIconVisible(false); - } } void CommonPaletteTool::OnViewClicked(views::View* sender) { @@ -93,16 +91,16 @@ highlight_view_ = new HoverHighlightView(this); highlight_view_->SetBorder( - views::Border::CreateEmptyBorder(0, kMenuSeparatorVerticalPadding, 0, 0)); + views::Border::CreateEmptyBorder(0, kMenuExtraMarginFromLeftEdge, 0, 0)); const int interior_button_padding = (kMenuButtonSize - kMenuIconSize) / 2; - highlight_view_->AddIconAndLabelCustomSize( - icon, name, false, kMenuIconSize, interior_button_padding, - interior_button_padding + kMenuSeparatorVerticalPadding); + highlight_view_->AddIconAndLabelCustomSize(icon, name, false, kMenuIconSize, + interior_button_padding, + kTrayPopupPaddingHorizontal); highlight_view_->AddRightIcon(check, kMenuIconSize); + highlight_view_->set_custom_height(kMenuButtonSize); + highlight_view_->text_label()->SetFontList(GetLabelFont()); - if (enabled()) - highlight_view_->SetHighlight(true); - else + if (!enabled()) highlight_view_->SetRightIconVisible(false); return highlight_view_;
diff --git a/ash/common/system/chromeos/palette/common_palette_tool.h b/ash/common/system/chromeos/palette/common_palette_tool.h index fb9419c..1c9d59a6 100644 --- a/ash/common/system/chromeos/palette/common_palette_tool.h +++ b/ash/common/system/chromeos/palette/common_palette_tool.h
@@ -25,7 +25,6 @@ ~CommonPaletteTool() override; // PaletteTool: - views::View* CreateView() override; void OnViewDestroyed() override; void OnEnable() override; void OnDisable() override;
diff --git a/ash/common/system/chromeos/palette/palette_tray.cc b/ash/common/system/chromeos/palette/palette_tray.cc index bd75cc5..4ffe589 100644 --- a/ash/common/system/chromeos/palette/palette_tray.cc +++ b/ash/common/system/chromeos/palette/palette_tray.cc
@@ -49,27 +49,26 @@ // Width of the palette itself (dp). const int kPaletteWidth = 332; +// Padding at the top/bottom of the palette (dp). +const int kPalettePaddingOnTop = 4; +const int kPalettePaddingOnBottom = 4; + // Size of icon in the shelf (dp). const int kShelfIconSize = 18; +// Vertical margin around the title view elements so that the title view height +// matches kMenuButtonSize. +const int kVerticalMarginAroundTitleView = 1; + // Margins between the title view and the edges around it (dp). -const int kPaddingBetweenTitleAndTopEdge = 4; const int kPaddingBetweenTitleAndLeftEdge = 12; const int kPaddingBetweenTitleAndSeparator = 3; -// Margin between the separator beneath the title and the first action (dp). -const int kPaddingActionsAndTopSeparator = 4; +// The distance between the title, help, and settings button in the title (dp). +const int kHorizontalPaddingBetweenTitleEntries = 2; -// Size of the header icons (dp). -const int kIconSize = 20; - -// Creates a separator. -views::Separator* CreateSeparator(views::Separator::Orientation orientation) { - views::Separator* separator = - new views::Separator(views::Separator::HORIZONTAL); - separator->SetColor(ash::kBorderDarkColor); - return separator; -} +// Color of the separator. +const SkColor kPaletteSeparatorColor = SkColorSetARGB(0x1E, 0x00, 0x00, 0x00); // Returns true if we are in a user session that can show the stylus tools. bool IsInUserSession() { @@ -82,19 +81,25 @@ LoginStatus::KIOSK_APP; } +// Returns the font used by the title view. +const gfx::FontList& GetTitleFont() { + // TODO(tdanderson|jdufault): Use TrayPopupItemStyle instead. + return ui::ResourceBundle::GetSharedInstance().GetFontListWithDelta( + 2, gfx::Font::FontStyle::NORMAL, gfx::Font::Weight::MEDIUM); +} + class TitleView : public views::View, public views::ButtonListener { public: explicit TitleView(PaletteTray* palette_tray) : palette_tray_(palette_tray) { - auto& rb = ui::ResourceBundle::GetSharedInstance(); - - auto* box_layout = - new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0); + auto* box_layout = new views::BoxLayout( + views::BoxLayout::kHorizontal, 0, kVerticalMarginAroundTitleView, + kHorizontalPaddingBetweenTitleEntries); SetLayoutManager(box_layout); views::Label* text_label = new views::Label(l10n_util::GetStringUTF16(IDS_ASH_STYLUS_TOOLS_TITLE)); text_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); - text_label->SetFontList(rb.GetFontList(ui::ResourceBundle::BoldFont)); + text_label->SetFontList(GetTitleFont()); AddChildView(text_label); box_layout->SetFlexForView(text_label, 1); @@ -102,7 +107,6 @@ gfx::CreateVectorIcon(kSystemMenuSettingsIcon, kMenuIconColor); gfx::ImageSkia help_icon = gfx::CreateVectorIcon(kSystemMenuHelpIcon, kMenuIconColor); - DCHECK_EQ(kIconSize, help_icon.width()); help_button_ = new ash::TrayPopupHeaderButton(this, help_icon, IDS_ASH_STATUS_TRAY_HELP); @@ -205,6 +209,8 @@ if (bubble_) return false; + DCHECK(tray_container()); + views::TrayBubbleView::InitParams init_params( views::TrayBubbleView::ANCHOR_TYPE_TRAY, GetAnchorAlignment(), kPaletteWidth, kPaletteWidth); @@ -218,29 +224,40 @@ // Make sure to block auto hiding before that check happens. should_block_shelf_auto_hide_ = true; - // Create view, customize it. + // TODO(tdanderson): Refactor into common row layout code. + // TODO(tdanderson|jdufault): Add material design ripple effects to the menu + // rows. + + // Create and customize bubble view. views::TrayBubbleView* bubble_view = views::TrayBubbleView::Create(tray_container(), this, &init_params); bubble_view->SetArrowPaintType(views::BubbleBorder::PAINT_NONE); - bubble_view->UseCompactMargins(); - bubble_view->set_margins(gfx::Insets(0, 0, 0, 0)); + bubble_view->set_margins( + gfx::Insets(kPalettePaddingOnTop, 0, kPalettePaddingOnBottom, 0)); - // Add child views. + // Add title. auto* title_view = new TitleView(this); - title_view->SetBorder(views::Border::CreateEmptyBorder(gfx::Insets( - kPaddingBetweenTitleAndTopEdge, kPaddingBetweenTitleAndLeftEdge, - kPaddingBetweenTitleAndSeparator, 0))); + title_view->SetBorder(views::Border::CreateEmptyBorder( + gfx::Insets(0, kPaddingBetweenTitleAndLeftEdge, 0, 0))); bubble_view->AddChildView(title_view); - views::Separator* separator = CreateSeparator(views::Separator::HORIZONTAL); - separator->SetBorder(views::Border::CreateEmptyBorder( - gfx::Insets(0, 0, kPaddingActionsAndTopSeparator, 0))); + // Add horizontal separator. + views::Separator* separator = + new views::Separator(views::Separator::HORIZONTAL); + separator->SetColor(kPaletteSeparatorColor); + separator->SetBorder(views::Border::CreateEmptyBorder(gfx::Insets( + kPaddingBetweenTitleAndSeparator, 0, kMenuSeparatorVerticalPadding, 0))); bubble_view->AddChildView(separator); - AddToolsToView(bubble_view); + + // Add palette tools. + // TODO(tdanderson|jdufault): Use SystemMenuButton to get the material design + // ripples. + std::vector<PaletteToolView> views = palette_tool_manager_->CreateViews(); + for (const PaletteToolView& view : views) + bubble_view->AddChildView(view.view); // Show the bubble. bubble_.reset(new ash::TrayBubbleWrapper(this, bubble_view)); - SetDrawBackgroundAsActive(true); return true; } @@ -252,12 +269,6 @@ return bubble_ && bubble_->bubble_view()->GetBoundsInScreen().Contains(point); } -void PaletteTray::AddToolsToView(views::View* host) { - std::vector<PaletteToolView> views = palette_tool_manager_->CreateViews(); - for (const PaletteToolView& view : views) - host->AddChildView(view.view); -} - void PaletteTray::SessionStateChanged( SessionStateDelegate::SessionState state) { UpdateIconVisibility();
diff --git a/ash/common/system/chromeos/palette/palette_tray.h b/ash/common/system/chromeos/palette/palette_tray.h index 2374744..4805e12 100644 --- a/ash/common/system/chromeos/palette/palette_tray.h +++ b/ash/common/system/chromeos/palette/palette_tray.h
@@ -110,8 +110,6 @@ // Called when the palette enabled pref has changed. void OnPaletteEnabledPrefChanged(bool enabled); - void AddToolsToView(views::View* host); - std::unique_ptr<PaletteToolManager> palette_tool_manager_; std::unique_ptr<TrayBubbleWrapper> bubble_;
diff --git a/ash/common/system/tray/hover_highlight_view.cc b/ash/common/system/tray/hover_highlight_view.cc index 1cf88c1..075d776d 100644 --- a/ash/common/system/tray/hover_highlight_view.cc +++ b/ash/common/system/tray/hover_highlight_view.cc
@@ -225,9 +225,13 @@ gfx::Size HoverHighlightView::GetPreferredSize() const { gfx::Size size = ActionableView::GetPreferredSize(); - int height = GetTrayConstant(TRAY_POPUP_ITEM_HEIGHT); - if (!expandable_ || size.height() < height) - size.set_height(height); + const int default_height = GetTrayConstant(TRAY_POPUP_ITEM_HEIGHT); + + if (custom_height_) + size.set_height(custom_height_); + else if (!expandable_ || size.height() < default_height) + size.set_height(default_height); + return size; }
diff --git a/ash/common/system/tray/hover_highlight_view.h b/ash/common/system/tray/hover_highlight_view.h index 7f13fb6..54698d8 100644 --- a/ash/common/system/tray/hover_highlight_view.h +++ b/ash/common/system/tray/hover_highlight_view.h
@@ -79,6 +79,10 @@ // just uses a bold font. void SetHighlight(bool hightlight); + // Set a custom height for the view. A value of 0 means that no custom height + // is set. + void set_custom_height(int custom_height) { custom_height_ = custom_height; } + void set_highlight_color(SkColor color) { highlight_color_ = color; } void set_default_color(SkColor color) { default_color_ = color; } void set_text_highlight_color(SkColor c) { text_highlight_color_ = c; } @@ -130,6 +134,7 @@ bool expandable_ = false; bool checkable_ = false; bool checked_ = false; + int custom_height_ = 0; base::string16 tooltip_; DISALLOW_COPY_AND_ASSIGN(HoverHighlightView);
diff --git a/ash/common/system/tray/tray_constants.cc b/ash/common/system/tray/tray_constants.cc index af23214..11923f0 100644 --- a/ash/common/system/tray/tray_constants.cc +++ b/ash/common/system/tray/tray_constants.cc
@@ -76,14 +76,13 @@ kTrayPopupMinWidth - (kNotificationIconWidth + kNotificationButtonWidth + (kTrayPopupPaddingHorizontal / 2) * 3); -const int kMessageCenterBubblePadding = 4; - const int kTrayIconSize = 16; const SkColor kTrayIconColor = SK_ColorWHITE; const int kMenuIconSize = 20; const SkColor kMenuIconColor = gfx::kChromeIconGrey; const int kMenuButtonSize = 48; const int kMenuSeparatorVerticalPadding = 4; +const int kMenuExtraMarginFromLeftEdge = 4; const int kHitRegionPadding = 4; const SkColor kSeparatorColor = SkColorSetA(SK_ColorWHITE, 0x4D);
diff --git a/ash/common/system/tray/tray_constants.h b/ash/common/system/tray/tray_constants.h index 22873ef..cd1c8e8 100644 --- a/ash/common/system/tray/tray_constants.h +++ b/ash/common/system/tray/tray_constants.h
@@ -72,8 +72,6 @@ extern const int kNotificationButtonWidth; extern const int kTrayNotificationContentsWidth; -extern const int kMessageCenterBubblePadding; - // Extra padding used to adjust hitting region around tray items. extern const int kHitRegionPadding; @@ -99,6 +97,8 @@ extern const int kMenuButtonSize; // The vertical padding for the system menu separator. extern const int kMenuSeparatorVerticalPadding; +// The horizontal padding for the system menu separator. +extern const int kMenuExtraMarginFromLeftEdge; enum TrayConstant { // A legacy height value used in non-MD calculations for applying additional
diff --git a/base/debug/activity_tracker.cc b/base/debug/activity_tracker.cc index dc1f529a..7e6aef20 100644 --- a/base/debug/activity_tracker.cc +++ b/base/debug/activity_tracker.cc
@@ -66,6 +66,89 @@ return ForThread(thread_ref.as_id); } +ActivityTrackerMemoryAllocator::ActivityTrackerMemoryAllocator( + PersistentMemoryAllocator* allocator, + uint32_t object_type, + uint32_t object_free_type, + size_t object_size, + size_t cache_size) + : allocator_(allocator), + object_type_(object_type), + object_free_type_(object_free_type), + object_size_(object_size), + cache_size_(cache_size), + iterator_(allocator), + cache_values_(new Reference[cache_size]), + cache_used_(0) { + DCHECK(allocator); +} + +ActivityTrackerMemoryAllocator::~ActivityTrackerMemoryAllocator() {} + +ActivityTrackerMemoryAllocator::Reference +ActivityTrackerMemoryAllocator::GetObjectReference() { + // First see if there is a cached value that can be returned. This is much + // faster than searching the memory system for free blocks. + while (cache_used_ > 0) { + Reference cached = cache_values_[--cache_used_]; + // Change the type of the cached object to the proper type and return it. + // If the type-change fails that means another thread has taken this from + // under us (via the search below) so ignore it and keep trying. + if (allocator_->ChangeType(cached, object_type_, object_free_type_)) + return cached; + } + + // Fetch the next "free" object from persistent memory. Rather than restart + // the iterator at the head each time and likely waste time going again + // through objects that aren't relevant, the iterator continues from where + // it last left off and is only reset when the end is reached. If the + // returned reference matches |last|, then it has wrapped without finding + // anything. + const Reference last = iterator_.GetLast(); + while (true) { + uint32_t type; + Reference found = iterator_.GetNext(&type); + if (found && type == object_free_type_) { + // Found a free object. Change it to the proper type and return it. If + // the type-change fails that means another thread has taken this from + // under us so ignore it and keep trying. + if (allocator_->ChangeType(found, object_type_, object_free_type_)) + return found; + } + if (found == last) { + // Wrapped. No desired object was found. + break; + } + if (!found) { + // Reached end; start over at the beginning. + iterator_.Reset(); + } + } + + // No free block was found so instead allocate a new one. + Reference allocated = allocator_->Allocate(object_size_, object_type_); + if (allocated) + allocator_->MakeIterable(allocated); + return allocated; +} + +void ActivityTrackerMemoryAllocator::ReleaseObjectReference(Reference ref) { + // Zero the memory so that it is ready for immediate use if needed later. + char* mem_base = allocator_->GetAsObject<char>(ref, object_type_); + DCHECK(mem_base); + memset(mem_base, 0, object_size_); + + // Mark object as free. + bool success = allocator_->ChangeType(ref, object_free_type_, object_type_); + DCHECK(success); + + // Add this reference to our "free" cache if there is space. If not, the type + // has still been changed to indicate that it is free so this (or another) + // thread can find it, albeit more slowly, using the iteration method above. + if (cache_used_ < cache_size_) + cache_values_[cache_used_++] = ref; +} + // static void Activity::FillFrom(Activity* activity, const void* origin, @@ -499,60 +582,25 @@ ThreadActivityTracker* GlobalActivityTracker::CreateTrackerForCurrentThread() { DCHECK(!this_thread_tracker_.Get()); - PersistentMemoryAllocator::Reference mem_reference = - PersistentMemoryAllocator::kReferenceNull; - DCHECK(!mem_reference); // invalid_value should be checkable with ! + PersistentMemoryAllocator::Reference mem_reference; - while (true) { - // Get the first available memory from the top of the FIFO. - if (!available_memories_.pop(&mem_reference)) - break; - - // Turn the reference back into one of the activity-tracker type. This can - // fail if something else has already taken the block and changed its type. - if (allocator_->ChangeType(mem_reference, kTypeIdActivityTracker, - kTypeIdActivityTrackerFree)) { - break; - } + { + base::AutoLock autolock(thread_tracker_allocator_lock_); + mem_reference = thread_tracker_allocator_.GetObjectReference(); } - // Handle the case where no known available memories were found. if (!mem_reference) { - // Allocate a block of memory from the persistent segment. - mem_reference = - allocator_->Allocate(stack_memory_size_, kTypeIdActivityTracker); - if (mem_reference) { - // Success. Make the allocation iterable so it can be found later. - allocator_->MakeIterable(mem_reference); - } else { - // Failure. Look for any free blocks that weren't held in the cache - // of available memories and try to claim it. This can happen if the - // |available_memories_| stack isn't sufficiently large to hold all - // released memories or if multiple independent processes are sharing - // the memory segment. - PersistentMemoryAllocator::Iterator iter(allocator_.get()); - while ((mem_reference = iter.GetNextOfType(kTypeIdActivityTrackerFree)) != - 0) { - if (allocator_->ChangeType(mem_reference, kTypeIdActivityTracker, - kTypeIdActivityTrackerFree)) { - break; - } - mem_reference = 0; - } - if (!mem_reference) { - // Dobule Failure. This shouldn't happen. But be graceful if it does, - // probably because the underlying allocator wasn't given enough memory - // to satisfy all possible requests. - NOTREACHED(); - // Report the thread-count at which the allocator was full so that the - // failure can be seen and underlying memory resized appropriately. - UMA_HISTOGRAM_COUNTS_1000( - "ActivityTracker.ThreadTrackers.MemLimitTrackerCount", - thread_tracker_count_.load(std::memory_order_relaxed)); - // Return null, just as if tracking wasn't enabled. - return nullptr; - } - } + // Failure. This shouldn't happen. But be graceful if it does, probably + // because the underlying allocator wasn't given enough memory to satisfy + // to all possible requests. + NOTREACHED(); + // Report the thread-count at which the allocator was full so that the + // failure can be seen and underlying memory resized appropriately. + UMA_HISTOGRAM_COUNTS_1000( + "ActivityTracker.ThreadTrackers.MemLimitTrackerCount", + thread_tracker_count_.load(std::memory_order_relaxed)); + // Return null, just as if tracking wasn't enabled. + return nullptr; } // Convert the memory block found above into an actual memory address. @@ -589,7 +637,11 @@ stack_memory_size_(ThreadActivityTracker::SizeForStackDepth(stack_depth)), this_thread_tracker_(&OnTLSDestroy), thread_tracker_count_(0), - available_memories_(kMaxThreadCount) { + thread_tracker_allocator_(allocator_.get(), + kTypeIdActivityTracker, + kTypeIdActivityTrackerFree, + stack_memory_size_, + kCachedThreadMemories) { // Ensure the passed memory is valid and empty (iterator finds nothing). uint32_t type; DCHECK(!PersistentMemoryAllocator::Iterator(allocator_.get()).GetNext(&type)); @@ -612,25 +664,13 @@ DCHECK(mem_reference); DCHECK(mem_base); - // Zero the memory so that it is ready for use if needed again later. It's - // better to clear the memory now, when a thread is exiting, than to do it - // when it is first needed by a thread doing actual work. - memset(mem_base, 0, stack_memory_size_); - // Remove the destructed tracker from the set of known ones. DCHECK_LE(1, thread_tracker_count_.load(std::memory_order_relaxed)); thread_tracker_count_.fetch_sub(1, std::memory_order_relaxed); - // The memory was within the persistent memory allocator. Change its type - // so it is effectively marked as "free". - allocator_->ChangeType(mem_reference, kTypeIdActivityTrackerFree, - kTypeIdActivityTracker); - - // Push this on the internal cache of available memory blocks so it can - // be found and reused quickly. If the push somehow exceeds the maximum - // size of the cache, it will fail but a fallback check in CreateTracker - // will find it by (slow) iteration. - available_memories_.push(mem_reference); + // Release this memory for re-use at a later time. + base::AutoLock autolock(thread_tracker_allocator_lock_); + thread_tracker_allocator_.ReleaseObjectReference(mem_reference); } // static
diff --git a/base/debug/activity_tracker.h b/base/debug/activity_tracker.h index 2cf4850..566b682b 100644 --- a/base/debug/activity_tracker.h +++ b/base/debug/activity_tracker.h
@@ -125,6 +125,53 @@ // A "null" activity-data that can be passed to indicate "do not change". extern const ActivityData kNullActivityData; + +// A helper class that is used for managing memory allocations within a +// persistent memory allocator. Instances of this class are NOT thread-safe. +// Use from a single thread or protect access with a lock. +class ActivityTrackerMemoryAllocator { + public: + using Reference = PersistentMemoryAllocator::Reference; + + // Creates a instance for allocating objects of a fixed |object_type|, a + // corresponding |object_free| type, and the |object_size|. An internal + // cache of the last |cache_size| released references will be kept for + // quick future fetches. + ActivityTrackerMemoryAllocator(PersistentMemoryAllocator* allocator, + uint32_t object_type, + uint32_t object_free_type, + size_t object_size, + size_t cache_size); + ~ActivityTrackerMemoryAllocator(); + + // Gets a reference to an object of the configured type. This can return + // a null reference if it was not possible to allocate the memory. + Reference GetObjectReference(); + + // Returns an object to the "free" pool. + void ReleaseObjectReference(Reference ref); + + // The current "used size" of the internal cache, visible for testing. + size_t cache_used() const { return cache_used_; } + + private: + PersistentMemoryAllocator* const allocator_; + const uint32_t object_type_; + const uint32_t object_free_type_; + const size_t object_size_; + const size_t cache_size_; + + // An iterator for going through persistent memory looking for free'd objects. + PersistentMemoryAllocator::Iterator iterator_; + + // The cache of released object memories. + std::unique_ptr<Reference[]> cache_values_; + size_t cache_used_; + + DISALLOW_COPY_AND_ASSIGN(ActivityTrackerMemoryAllocator); +}; + + // This structure is the full contents recorded for every activity pushed // onto the stack. The |activity_type| indicates what is actually stored in // the |data| field. All fields must be explicitly sized types to ensure no @@ -344,46 +391,6 @@ // the thread trackers is taken from a PersistentMemoryAllocator which allows // for the data to be analyzed by a parallel process or even post-mortem. class BASE_EXPORT GlobalActivityTracker { - template <typename T> - class ThreadSafeStack { - public: - ThreadSafeStack(size_t size) - : size_(size), values_(new T[size]), used_(0) {} - ~ThreadSafeStack() {} - - size_t size() { return size_; } - size_t used() { - base::AutoLock autolock(lock_); - return used_; - } - - bool push(T value) { - base::AutoLock autolock(lock_); - if (used_ == size_) - return false; - values_[used_++] = value; - return true; - } - - bool pop(T* out_value) { - base::AutoLock autolock(lock_); - if (used_ == 0) - return false; - *out_value = values_[--used_]; - return true; - } - - private: - const size_t size_; - - std::unique_ptr<T[]> values_; - size_t used_; - base::Lock lock_; - - private: - DISALLOW_COPY_AND_ASSIGN(ThreadSafeStack); - }; - public: // Type identifiers used when storing in persistent memory so they can be // identified during extraction; the first 4 bytes of the SHA1 of the name @@ -393,7 +400,7 @@ // can recognize records of this type within an allocator. enum : uint32_t { kTypeIdActivityTracker = 0x5D7381AF + 1, // SHA1(ActivityTracker) v1 - kTypeIdActivityTrackerFree = 0x3F0272FB + 1, // SHA1(ActivityTrackerFree) + kTypeIdActivityTrackerFree = ~kTypeIdActivityTracker, }; // This is a thin wrapper around the thread-tracker's ScopedActivity that @@ -499,6 +506,7 @@ // The maximum number of threads that can be tracked within a process. If // more than this number run concurrently, tracking of new ones may cease. kMaxThreadCount = 100, + kCachedThreadMemories = 10, }; // A thin wrapper around the main thread-tracker that keeps additional @@ -550,9 +558,9 @@ // The number of thread trackers currently active. std::atomic<int> thread_tracker_count_; - // A cache of thread-tracker memories that have been previously freed and - // thus can be re-used instead of allocating new ones. - ThreadSafeStack<PersistentMemoryAllocator::Reference> available_memories_; + // A caching memory allocator for thread-tracker objects. + ActivityTrackerMemoryAllocator thread_tracker_allocator_; + base::Lock thread_tracker_allocator_lock_; // The active global activity tracker. static GlobalActivityTracker* g_tracker_;
diff --git a/base/debug/activity_tracker_unittest.cc b/base/debug/activity_tracker_unittest.cc index f422e50..26c0b51 100644 --- a/base/debug/activity_tracker_unittest.cc +++ b/base/debug/activity_tracker_unittest.cc
@@ -74,7 +74,7 @@ GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get(); if (!global_tracker) return 0; - return global_tracker->available_memories_.used(); + return global_tracker->thread_tracker_allocator_.cache_used(); } static void DoNothing() {}
diff --git a/base/metrics/persistent_memory_allocator.cc b/base/metrics/persistent_memory_allocator.cc index fd8a73d..2b3bf17e 100644 --- a/base/metrics/persistent_memory_allocator.cc +++ b/base/metrics/persistent_memory_allocator.cc
@@ -133,7 +133,19 @@ PersistentMemoryAllocator::Iterator::Iterator( const PersistentMemoryAllocator* allocator, Reference starting_after) - : allocator_(allocator), last_record_(starting_after), record_count_(0) { + : allocator_(allocator), last_record_(0), record_count_(0) { + Reset(starting_after); +} + +void PersistentMemoryAllocator::Iterator::Reset() { + last_record_.store(kReferenceQueue, std::memory_order_relaxed); + record_count_.store(0, std::memory_order_relaxed); +} + +void PersistentMemoryAllocator::Iterator::Reset(Reference starting_after) { + last_record_.store(starting_after, std::memory_order_relaxed); + record_count_.store(0, std::memory_order_relaxed); + // Ensure that the starting point is a valid, iterable block (meaning it can // be read and has a non-zero "next" pointer). const volatile BlockHeader* block = @@ -145,6 +157,14 @@ } PersistentMemoryAllocator::Reference +PersistentMemoryAllocator::Iterator::GetLast() { + Reference last = last_record_.load(std::memory_order_relaxed); + if (last == kReferenceQueue) + return kReferenceNull; + return last; +} + +PersistentMemoryAllocator::Reference PersistentMemoryAllocator::Iterator::GetNext(uint32_t* type_return) { // Make a copy of the existing count of found-records, acquiring all changes // made to the allocator, notably "freeptr" (see comment in loop for why
diff --git a/base/metrics/persistent_memory_allocator.h b/base/metrics/persistent_memory_allocator.h index 7004afe..dea12a6 100644 --- a/base/metrics/persistent_memory_allocator.h +++ b/base/metrics/persistent_memory_allocator.h
@@ -56,6 +56,11 @@ // That means that multiple threads can share an iterator and the same // reference will not be returned twice. // + // The order of the items returned by an iterator matches the order in which + // MakeIterable() was called on them. Once an allocation is made iterable, + // it is always such so the only possible difference between successive + // iterations is for more to be added to the end. + // // Iteration, in general, is tolerant of corrupted memory. It will return // what it can and stop only when corruption forces it to. Bad corruption // could cause the same object to be returned many times but it will @@ -76,6 +81,17 @@ Iterator(const PersistentMemoryAllocator* allocator, Reference starting_after); + // Resets the iterator back to the beginning. + void Reset(); + + // Resets the iterator, resuming from the |starting_after| reference. + void Reset(Reference starting_after); + + // Returns the previously retrieved reference, or kReferenceNull if none. + // If constructor or reset with a starting_after location, this will return + // that value. + Reference GetLast(); + // Gets the next iterable, storing that type in |type_return|. The actual // return value is a reference to the allocation inside the allocator or // zero if there are no more. GetNext() may still be called again at a
diff --git a/base/metrics/persistent_memory_allocator_unittest.cc b/base/metrics/persistent_memory_allocator_unittest.cc index 6039d3e..977d85fd 100644 --- a/base/metrics/persistent_memory_allocator_unittest.cc +++ b/base/metrics/persistent_memory_allocator_unittest.cc
@@ -121,12 +121,15 @@ // Ensure that the test-object can be made iterable. PersistentMemoryAllocator::Iterator iter1a(allocator_.get()); + EXPECT_EQ(0U, iter1a.GetLast()); uint32_t type; EXPECT_EQ(0U, iter1a.GetNext(&type)); allocator_->MakeIterable(block1); EXPECT_EQ(block1, iter1a.GetNext(&type)); EXPECT_EQ(1U, type); + EXPECT_EQ(block1, iter1a.GetLast()); EXPECT_EQ(0U, iter1a.GetNext(&type)); + EXPECT_EQ(block1, iter1a.GetLast()); // Create second test-object and ensure everything is good and it cannot // be confused with test-object of another type. @@ -146,6 +149,24 @@ allocator_->MakeIterable(block2); EXPECT_EQ(block2, iter1a.GetNext(&type)); EXPECT_EQ(2U, type); + EXPECT_EQ(block2, iter1a.GetLast()); + EXPECT_EQ(0U, iter1a.GetNext(&type)); + EXPECT_EQ(block2, iter1a.GetLast()); + + // Check that the iterator can be reset to the beginning. + iter1a.Reset(); + EXPECT_EQ(0U, iter1a.GetLast()); + EXPECT_EQ(block1, iter1a.GetNext(&type)); + EXPECT_EQ(block1, iter1a.GetLast()); + EXPECT_EQ(block2, iter1a.GetNext(&type)); + EXPECT_EQ(block2, iter1a.GetLast()); + EXPECT_EQ(0U, iter1a.GetNext(&type)); + + // Check that the iterator can be reset to an arbitrary location. + iter1a.Reset(block1); + EXPECT_EQ(block1, iter1a.GetLast()); + EXPECT_EQ(block2, iter1a.GetNext(&type)); + EXPECT_EQ(block2, iter1a.GetLast()); EXPECT_EQ(0U, iter1a.GetNext(&type)); // Check that iteration can begin after an arbitrary location.
diff --git a/base/task_scheduler/scheduler_worker.cc b/base/task_scheduler/scheduler_worker.cc index 1f5625c..59b756c 100644 --- a/base/task_scheduler/scheduler_worker.cc +++ b/base/task_scheduler/scheduler_worker.cc
@@ -45,7 +45,7 @@ WaitForWork(); while (!outer_->task_tracker_->IsShutdownComplete() && - !outer_->ShouldExitForTesting()) { + !outer_->should_exit_for_testing_.IsSet()) { DCHECK(outer_); #if defined(OS_MACOSX) @@ -217,10 +217,11 @@ } void SchedulerWorker::JoinForTesting() { - { - AutoSchedulerLock auto_lock(should_exit_for_testing_lock_); - should_exit_for_testing_ = true; - } + // It's not possible to have concurrent calls to this method because a DCHECK + // fails when AtomicFlag::Set() calls aren't sequenced. + DCHECK(!should_exit_for_testing_.IsSet()); + should_exit_for_testing_.Set(); + WakeUp(); // Normally holding a lock and joining is dangerous. However, since this is @@ -250,7 +251,7 @@ } std::unique_ptr<SchedulerWorker::Thread> SchedulerWorker::Detach() { - DCHECK(!ShouldExitForTesting()) << "Worker was already joined"; + DCHECK(!should_exit_for_testing_.IsSet()) << "Worker was already joined"; AutoSchedulerLock auto_lock(thread_lock_); // If a wakeup is pending, then a WakeUp() came in while we were deciding to // detach. This means we can't go away anymore since we would break the @@ -270,10 +271,5 @@ CreateThread(); } -bool SchedulerWorker::ShouldExitForTesting() const { - AutoSchedulerLock auto_lock(should_exit_for_testing_lock_); - return should_exit_for_testing_; -} - } // namespace internal } // namespace base
diff --git a/base/task_scheduler/scheduler_worker.h b/base/task_scheduler/scheduler_worker.h index ec49eb8..b9958be 100644 --- a/base/task_scheduler/scheduler_worker.h +++ b/base/task_scheduler/scheduler_worker.h
@@ -10,6 +10,7 @@ #include "base/base_export.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/synchronization/atomic_flag.h" #include "base/synchronization/waitable_event.h" #include "base/task_scheduler/scheduler_lock.h" #include "base/task_scheduler/sequence.h" @@ -136,8 +137,6 @@ void CreateThreadAssertSynchronized(); - bool ShouldExitForTesting() const; - // Synchronizes access to |thread_|. mutable SchedulerLock thread_lock_; @@ -152,11 +151,8 @@ const std::unique_ptr<Delegate> delegate_; TaskTracker* const task_tracker_; - // Synchronizes access to |should_exit_for_testing_|. - mutable SchedulerLock should_exit_for_testing_lock_; - - // True once JoinForTesting() has been called. - bool should_exit_for_testing_ = false; + // Set once JoinForTesting() has been called. + AtomicFlag should_exit_for_testing_; DISALLOW_COPY_AND_ASSIGN(SchedulerWorker); };
diff --git a/base/task_scheduler/scheduler_worker_pool_impl.cc b/base/task_scheduler/scheduler_worker_pool_impl.cc index e804bbd..f14e5f9 100644 --- a/base/task_scheduler/scheduler_worker_pool_impl.cc +++ b/base/task_scheduler/scheduler_worker_pool_impl.cc
@@ -34,6 +34,8 @@ constexpr char kPoolNameSuffix[] = "Pool"; constexpr char kDetachDurationHistogramPrefix[] = "TaskScheduler.DetachDuration."; +constexpr char kNumTasksBeforeDetachHistogramPrefix[] = + "TaskScheduler.NumTasksBeforeDetach."; constexpr char kNumTasksBetweenWaitsHistogramPrefix[] = "TaskScheduler.NumTasksBetweenWaits."; constexpr char kTaskLatencyHistogramPrefix[] = "TaskScheduler.TaskLatency."; @@ -280,6 +282,10 @@ // TaskScheduler.NumTasksBetweenWaits histogram was recorded. size_t num_tasks_since_last_wait_ = 0; + // Number of tasks executed since the last time the + // TaskScheduler.NumTasksBeforeDetach histogram was recorded. + size_t num_tasks_since_last_detach_ = 0; + subtle::Atomic32 num_single_threaded_runners_ = 0; const int index_; @@ -435,7 +441,7 @@ // Wake up a worker to process |sequence|. if (worker) - worker->WakeUp(); + WakeUpWorker(worker); else WakeUpOneWorker(); } @@ -486,8 +492,12 @@ DCHECK_EQ(num_tasks_since_last_wait_, 0U); + // Record histograms if the worker detached in the past. if (!detach_duration.is_max()) { outer_->detach_duration_histogram_->AddTime(detach_duration); + outer_->num_tasks_before_detach_histogram_->Add( + num_tasks_since_last_detach_); + num_tasks_since_last_detach_ = 0; did_detach_since_last_get_work_ = true; } @@ -593,6 +603,7 @@ DidRunTaskWithPriority(TaskPriority task_priority, const TimeDelta& task_latency) { ++num_tasks_since_last_wait_; + ++num_tasks_since_last_detach_; const int priority_index = static_cast<int>(task_priority); @@ -673,6 +684,16 @@ TimeDelta::FromHours(1), 50, HistogramBase::kUmaTargetedHistogramFlag)), + // Mimics the UMA_HISTOGRAM_COUNTS_1000 macro. A SchedulerWorker is + // expected to run between zero and a few hundreds of tasks before + // detaching. When it runs more than 1000 tasks, there is no need to know + // the exact number of tasks that ran. + num_tasks_before_detach_histogram_(Histogram::FactoryGet( + kNumTasksBeforeDetachHistogramPrefix + name_ + kPoolNameSuffix, + 1, + 1000, + 50, + HistogramBase::kUmaTargetedHistogramFlag)), // Mimics the UMA_HISTOGRAM_COUNTS_100 macro. A SchedulerWorker is // expected to run between zero and a few tens of tasks between waits. // When it runs more than 100 tasks, there is no need to know the exact @@ -696,21 +717,24 @@ AutoSchedulerLock auto_lock(idle_workers_stack_lock_); DCHECK(workers_.empty()); + workers_.resize(max_threads); - for (size_t i = 0; i < max_threads; ++i) { - // The last SchedulerWorker added to the idle stack should be ALIVE. + // Create workers and push them to the idle stack in reverse order of index. + // This ensures that they are woken up in order of index and that the ALIVE + // worker is on top of the stack. + for (int index = max_threads - 1; index >= 0; --index) { const SchedulerWorker::InitialState initial_state = - (i == max_threads - 1) ? SchedulerWorker::InitialState::ALIVE - : SchedulerWorker::InitialState::DETACHED; + (index == 0) ? SchedulerWorker::InitialState::ALIVE + : SchedulerWorker::InitialState::DETACHED; std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create( - priority_hint, MakeUnique<SchedulerWorkerDelegateImpl>( - this, re_enqueue_sequence_callback, - &shared_priority_queue_, static_cast<int>(i)), + priority_hint, + MakeUnique<SchedulerWorkerDelegateImpl>( + this, re_enqueue_sequence_callback, &shared_priority_queue_, index), task_tracker_, initial_state); if (!worker) break; idle_workers_stack_.Push(worker.get()); - workers_.push_back(std::move(worker)); + workers_[index] = std::move(worker); } #if DCHECK_IS_ON() @@ -720,6 +744,12 @@ return !workers_.empty(); } +void SchedulerWorkerPoolImpl::WakeUpWorker(SchedulerWorker* worker) { + DCHECK(worker); + RemoveFromIdleWorkersStack(worker); + worker->WakeUp(); +} + void SchedulerWorkerPoolImpl::WakeUpOneWorker() { SchedulerWorker* worker; {
diff --git a/base/task_scheduler/scheduler_worker_pool_impl.h b/base/task_scheduler/scheduler_worker_pool_impl.h index a621f79..cab7b878 100644 --- a/base/task_scheduler/scheduler_worker_pool_impl.h +++ b/base/task_scheduler/scheduler_worker_pool_impl.h
@@ -94,7 +94,11 @@ scoped_refptr<Sequence> sequence, SchedulerWorker* worker) override; - const HistogramBase* num_tasks_between_waits_histogram_for_testing() const { + const HistogramBase* num_tasks_before_detach_histogram() const { + return num_tasks_before_detach_histogram_; + } + + const HistogramBase* num_tasks_between_waits_histogram() const { return num_tasks_between_waits_histogram_; } @@ -114,6 +118,9 @@ size_t max_threads, const ReEnqueueSequenceCallback& re_enqueue_sequence_callback); + // Wakes up |worker|. + void WakeUpWorker(SchedulerWorker* worker); + // Wakes up the last worker from this worker pool to go idle, if any. void WakeUpOneWorker(); @@ -159,7 +166,11 @@ // details in GetWork()). mutable SchedulerLock idle_workers_stack_lock_; - // Stack of idle workers. + // Stack of idle workers. Initially, all workers are on this stack. A worker + // is removed from the stack before its WakeUp() function is called and when + // it receives work from GetWork() (a worker calls GetWork() when its sleep + // timeout expires, even if its WakeUp() method hasn't been called). A worker + // is pushed on this stack when it receives nullptr from GetWork(). SchedulerWorkerStack idle_workers_stack_; // Signaled when all workers become idle. @@ -181,6 +192,10 @@ // leaked. HistogramBase* const detach_duration_histogram_; + // TaskScheduler.NumTasksBeforeDetach.[worker pool name] histogram. + // Intentionally leaked. + HistogramBase* const num_tasks_before_detach_histogram_; + // TaskScheduler.NumTasksBetweenWaits.[worker pool name] histogram. // Intentionally leaked. HistogramBase* const num_tasks_between_waits_histogram_;
diff --git a/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc b/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc index 0f8475a6..b67847a 100644 --- a/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc +++ b/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc
@@ -593,7 +593,11 @@ protected: void SetUp() override {} - void TearDown() override { worker_pool_->JoinForTesting(); } + void TearDown() override { + // |worker_pool_| initialization is done in test body. + if (worker_pool_) + worker_pool_->JoinForTesting(); + } private: std::unique_ptr<StatisticsRecorder> statistics_recorder_ = @@ -633,15 +637,10 @@ worker_pool_->WaitForAllWorkersIdleForTesting(); // Verify that counts were recorded to the histogram as expected. - EXPECT_EQ(0, worker_pool_->num_tasks_between_waits_histogram_for_testing() - ->SnapshotSamples() - ->GetCount(0)); - EXPECT_EQ(1, worker_pool_->num_tasks_between_waits_histogram_for_testing() - ->SnapshotSamples() - ->GetCount(3)); - EXPECT_EQ(0, worker_pool_->num_tasks_between_waits_histogram_for_testing() - ->SnapshotSamples() - ->GetCount(10)); + const auto* histogram = worker_pool_->num_tasks_between_waits_histogram(); + EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(0)); + EXPECT_EQ(1, histogram->SnapshotSamples()->GetCount(3)); + EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10)); } namespace { @@ -697,31 +696,64 @@ for (const auto& task_started_event : task_started_events) task_started_event->Wait(); + const auto* histogram = worker_pool_->num_tasks_between_waits_histogram(); + // Verify that counts were recorded to the histogram as expected. // - The "0" bucket has a count of at least 1 because the SchedulerWorker on // top of the idle stack isn't allowed to detach when its sleep timeout // expires. Instead, it waits on its WaitableEvent again without running a // task. The count may be higher than 1 because of spurious wake ups before // the sleep timeout expires. - EXPECT_GE(worker_pool_->num_tasks_between_waits_histogram_for_testing() - ->SnapshotSamples() - ->GetCount(0), - 1); + EXPECT_GE(histogram->SnapshotSamples()->GetCount(0), 1); // - The "1" bucket has a count of |kNumWorkersInWorkerPool| because each // SchedulerWorker ran a task before waiting on its WaitableEvent at the // beginning of the test. EXPECT_EQ(static_cast<int>(kNumWorkersInWorkerPool), - worker_pool_->num_tasks_between_waits_histogram_for_testing() - ->SnapshotSamples() - ->GetCount(1)); - EXPECT_EQ(0, worker_pool_->num_tasks_between_waits_histogram_for_testing() - ->SnapshotSamples() - ->GetCount(10)); + histogram->SnapshotSamples()->GetCount(1)); + EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10)); tasks_can_exit_event.Signal(); worker_pool_->WaitForAllWorkersIdleForTesting(); worker_pool_->DisallowWorkerDetachmentForTesting(); } +TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBeforeDetach) { + InitializeWorkerPool(kReclaimTimeForDetachTests, kNumWorkersInWorkerPool); + auto task_runner = worker_pool_->CreateTaskRunnerWithTraits( + TaskTraits(), ExecutionMode::SINGLE_THREADED); + auto other_task_runner = worker_pool_->CreateTaskRunnerWithTraits( + TaskTraits(), ExecutionMode::SINGLE_THREADED); + + // Post 3 tasks and wait until they run. + task_runner->PostTask(FROM_HERE, Bind(&DoNothing)); + task_runner->PostTask(FROM_HERE, Bind(&DoNothing)); + task_runner->PostTask(FROM_HERE, Bind(&DoNothing)); + worker_pool_->WaitForAllWorkersIdleForTesting(); + + // To allow the SchedulerWorker associated with |task_runner| to detach: + // - Make sure it isn't on top of the idle stack by waking up another + // SchedulerWorker. + // - Release |task_runner|. + other_task_runner->PostTask(FROM_HERE, Bind(&DoNothing)); + task_runner = nullptr; + + // Allow the SchedulerWorker to detach. + PlatformThread::Sleep(kReclaimTimeForDetachTests + kExtraTimeToWaitForDetach); + + // Join the SchedulerWorkerPool. This forces SchedulerWorkers that detached + // during the test to record to the histogram. + worker_pool_->WaitForAllWorkersIdleForTesting(); + worker_pool_->DisallowWorkerDetachmentForTesting(); + worker_pool_->JoinForTesting(); + const auto* histogram = worker_pool_->num_tasks_before_detach_histogram(); + other_task_runner = nullptr; + worker_pool_.reset(); + + // Verify that counts were recorded to the histogram as expected. + EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(0)); + EXPECT_EQ(1, histogram->SnapshotSamples()->GetCount(3)); + EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10)); +} + } // namespace internal } // namespace base
diff --git a/base/trace_event/heap_profiler_allocation_context_tracker.cc b/base/trace_event/heap_profiler_allocation_context_tracker.cc index cbece2b1..f3a03fe9 100644 --- a/base/trace_event/heap_profiler_allocation_context_tracker.cc +++ b/base/trace_event/heap_profiler_allocation_context_tracker.cc
@@ -129,7 +129,9 @@ // hit if some TRACE_EVENT macro is unbalanced (a TRACE_EVENT_END* call // without a corresponding TRACE_EVENT_BEGIN). DCHECK(stack_frame == pseudo_stack_.back()) - << "Encountered an unmatched TRACE_EVENT_END"; + << "Encountered an unmatched TRACE_EVENT_END: " + << stack_frame.trace_event_name + << " vs event in stack: " << pseudo_stack_.back().trace_event_name; pseudo_stack_.pop_back(); }
diff --git a/base/trace_event/heap_profiler_allocation_context_tracker_unittest.cc b/base/trace_event/heap_profiler_allocation_context_tracker_unittest.cc index de19ea2..056aa2c 100644 --- a/base/trace_event/heap_profiler_allocation_context_tracker_unittest.cc +++ b/base/trace_event/heap_profiler_allocation_context_tracker_unittest.cc
@@ -27,6 +27,18 @@ const char kFroyo[] = "Froyo"; const char kGingerbread[] = "Gingerbread"; +const char kFilteringTraceConfig[] = + "{" + " \"event_filters\": [" + " {" + " \"excluded_categories\": []," + " \"filter_args\": {}," + " \"filter_predicate\": \"heap_profiler_predicate\"," + " \"included_categories\": [\"*\"]" + " }" + " ]" + "}"; + // Asserts that the fixed-size array |expected_backtrace| matches the backtrace // in |AllocationContextTracker::GetContextSnapshot|. template <size_t N> @@ -68,15 +80,15 @@ AllocationContextTracker::CaptureMode::PSEUDO_STACK); // Enabling memory-infra category sets default memory dump config which // includes filters for capturing pseudo stack. - TraceConfig config(MemoryDumpManager::kTraceCategory, ""); - TraceLog::GetInstance()->SetEnabled(config, TraceLog::RECORDING_MODE); + TraceConfig config(kFilteringTraceConfig); + TraceLog::GetInstance()->SetEnabled(config, TraceLog::FILTERING_MODE); AllocationContextTracker::SetCurrentThreadName(kThreadName); } void TearDown() override { AllocationContextTracker::SetCaptureMode( AllocationContextTracker::CaptureMode::DISABLED); - TraceLog::GetInstance()->SetDisabled(); + TraceLog::GetInstance()->SetDisabled(TraceLog::FILTERING_MODE); } };
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc index 9719a6c..28d5d56 100644 --- a/base/trace_event/memory_dump_manager.cc +++ b/base/trace_event/memory_dump_manager.cc
@@ -201,10 +201,33 @@ nullptr); #endif + TRACE_EVENT_WARMUP_CATEGORY(kTraceCategory); + + // TODO(ssid): This should be done in EnableHeapProfiling so that we capture + // more allocations (crbug.com/625170). + if (AllocationContextTracker::capture_mode() == + AllocationContextTracker::CaptureMode::PSEUDO_STACK && + !(TraceLog::GetInstance()->enabled_modes() & TraceLog::FILTERING_MODE)) { + // Create trace config with heap profiling filter. + TraceConfig::EventFilterConfig heap_profiler_filter_config( + TraceLog::TraceEventFilter::kHeapProfilerPredicate); + heap_profiler_filter_config.AddIncludedCategory("*"); + heap_profiler_filter_config.AddIncludedCategory( + MemoryDumpManager::kTraceCategory); + TraceConfig::EventFilters filters; + filters.push_back(heap_profiler_filter_config); + TraceConfig filtering_trace_config; + filtering_trace_config.SetEventFilters(filters); + + TraceLog::GetInstance()->SetEnabled(filtering_trace_config, + TraceLog::FILTERING_MODE); + } + // If tracing was enabled before initializing MemoryDumpManager, we missed the // OnTraceLogEnabled() event. Synthetize it so we can late-join the party. + // IsEnabled is called before adding observer to avoid calling + // OnTraceLogEnabled twice. bool is_tracing_already_enabled = TraceLog::GetInstance()->IsEnabled(); - TRACE_EVENT0(kTraceCategory, "init"); // Add to trace-viewer category list. TraceLog::GetInstance()->AddEnabledStateObserver(this); if (is_tracing_already_enabled) OnTraceLogEnabled();
diff --git a/base/trace_event/trace_config.cc b/base/trace_event/trace_config.cc index fdeb329..9a17adb9 100644 --- a/base/trace_event/trace_config.cc +++ b/base/trace_event/trace_config.cc
@@ -119,6 +119,17 @@ heap_profiler_options.Clear(); } +void TraceConfig::MemoryDumpConfig::Merge( + const TraceConfig::MemoryDumpConfig& config) { + triggers.insert(triggers.end(), config.triggers.begin(), + config.triggers.end()); + allowed_dump_modes.insert(config.allowed_dump_modes.begin(), + config.allowed_dump_modes.end()); + heap_profiler_options.breakdown_threshold_bytes = + std::min(heap_profiler_options.breakdown_threshold_bytes, + config.heap_profiler_options.breakdown_threshold_bytes); +} + TraceConfig::EventFilterConfig::EventFilterConfig( const std::string& predicate_name) : predicate_name_(predicate_name) {} @@ -355,9 +366,7 @@ included_categories_.clear(); } - memory_dump_config_.triggers.insert(memory_dump_config_.triggers.end(), - config.memory_dump_config_.triggers.begin(), - config.memory_dump_config_.triggers.end()); + memory_dump_config_.Merge(config.memory_dump_config_); disabled_categories_.insert(disabled_categories_.end(), config.disabled_categories_.begin(), @@ -368,6 +377,8 @@ synthetic_delays_.insert(synthetic_delays_.end(), config.synthetic_delays_.begin(), config.synthetic_delays_.end()); + event_filters_.insert(event_filters_.end(), config.event_filters().begin(), + config.event_filters().end()); } void TraceConfig::Clear() { @@ -416,6 +427,10 @@ if (dict.GetList(kSyntheticDelaysParam, &category_list)) SetSyntheticDelaysFromList(*category_list); + const base::ListValue* category_event_filters = nullptr; + if (dict.GetList(kEventFiltersParam, &category_event_filters)) + SetEventFiltersFromConfigList(*category_event_filters); + if (IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) { // If dump triggers not set, the client is using the legacy with just // category enabled. So, use the default periodic dump config. @@ -425,10 +440,6 @@ else SetDefaultMemoryDumpConfig(); } - - const base::ListValue* category_event_filters = nullptr; - if (dict.GetList(kEventFiltersParam, &category_event_filters)) - SetEventFilters(*category_event_filters); } void TraceConfig::InitializeFromConfigString(StringPiece config_string) { @@ -618,25 +629,9 @@ memory_dump_config_.triggers.push_back(kDefaultHeavyMemoryDumpTrigger); memory_dump_config_.triggers.push_back(kDefaultLightMemoryDumpTrigger); memory_dump_config_.allowed_dump_modes = GetDefaultAllowedMemoryDumpModes(); - - if (AllocationContextTracker::capture_mode() == - AllocationContextTracker::CaptureMode::PSEUDO_STACK) { - for (const auto& filter : event_filters_) { - if (filter.predicate_name() == - TraceLog::TraceEventFilter::kHeapProfilerPredicate) - return; - } - // Adds a filter predicate to filter all categories for the heap profiler. - // Note that the heap profiler predicate does not filter-out any events. - EventFilterConfig heap_profiler_config( - TraceLog::TraceEventFilter::kHeapProfilerPredicate); - heap_profiler_config.AddIncludedCategory("*"); - heap_profiler_config.AddIncludedCategory(MemoryDumpManager::kTraceCategory); - event_filters_.push_back(heap_profiler_config); - } } -void TraceConfig::SetEventFilters( +void TraceConfig::SetEventFiltersFromConfigList( const base::ListValue& category_event_filters) { event_filters_.clear();
diff --git a/base/trace_event/trace_config.h b/base/trace_event/trace_config.h index 87d0ae41..c10ed47 100644 --- a/base/trace_event/trace_config.h +++ b/base/trace_event/trace_config.h
@@ -71,6 +71,8 @@ // Reset the values in the config. void Clear(); + void Merge(const MemoryDumpConfig& config); + // Set of memory dump modes allowed for the tracing session. The explicitly // triggered dumps will be successful only if the dump mode is allowed in // the config. @@ -240,6 +242,9 @@ } const EventFilters& event_filters() const { return event_filters_; } + void SetEventFilters(const EventFilters& filter_configs) { + event_filters_ = filter_configs; + } private: FRIEND_TEST_ALL_PREFIXES(TraceConfigTest, TraceConfigFromValidLegacyFormat); @@ -281,7 +286,7 @@ const DictionaryValue& memory_dump_config); void SetDefaultMemoryDumpConfig(); - void SetEventFilters(const base::ListValue& event_filters); + void SetEventFiltersFromConfigList(const base::ListValue& event_filters); std::unique_ptr<DictionaryValue> ToDict() const; std::string ToTraceOptionsString() const;
diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h index 20ce662e..31b9f577 100644 --- a/base/trace_event/trace_event.h +++ b/base/trace_event/trace_event.h
@@ -55,7 +55,6 @@ #define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \ UNLIKELY(*INTERNAL_TRACE_EVENT_UID(category_group_enabled) & \ (base::trace_event::TraceLog::ENABLED_FOR_RECORDING | \ - base::trace_event::TraceLog::ENABLED_FOR_EVENT_CALLBACK | \ base::trace_event::TraceLog::ENABLED_FOR_ETW_EXPORT | \ base::trace_event::TraceLog::ENABLED_FOR_FILTERING))
diff --git a/base/trace_event/trace_event_unittest.cc b/base/trace_event/trace_event_unittest.cc index 84553781..459052b 100644 --- a/base/trace_event/trace_event_unittest.cc +++ b/base/trace_event/trace_event_unittest.cc
@@ -137,7 +137,8 @@ } void EndTraceAndFlushAsync(WaitableEvent* flush_complete_event) { - TraceLog::GetInstance()->SetDisabled(); + TraceLog::GetInstance()->SetDisabled(TraceLog::RECORDING_MODE | + TraceLog::FILTERING_MODE); TraceLog::GetInstance()->Flush( base::Bind(&TraceEventTestFixture::OnTraceDataCollected, base::Unretained(static_cast<TraceEventTestFixture*>(this)), @@ -2568,233 +2569,6 @@ EXPECT_EQ(args_string, "__stripped__"); } -class TraceEventCallbackTest : public TraceEventTestFixture { - public: - void SetUp() override { - TraceEventTestFixture::SetUp(); - ASSERT_EQ(NULL, s_instance); - s_instance = this; - } - void TearDown() override { - TraceLog::GetInstance()->SetDisabled(); - ASSERT_TRUE(s_instance); - s_instance = NULL; - TraceEventTestFixture::TearDown(); - } - - protected: - // For TraceEventCallbackAndRecordingX tests. - void VerifyCallbackAndRecordedEvents(size_t expected_callback_count, - size_t expected_recorded_count) { - // Callback events. - EXPECT_EQ(expected_callback_count, collected_events_names_.size()); - for (size_t i = 0; i < collected_events_names_.size(); ++i) { - EXPECT_EQ("callback", collected_events_categories_[i]); - EXPECT_EQ("yes", collected_events_names_[i]); - } - - // Recorded events. - EXPECT_EQ(expected_recorded_count, trace_parsed_.GetSize()); - EXPECT_TRUE(FindTraceEntry(trace_parsed_, "recording")); - EXPECT_FALSE(FindTraceEntry(trace_parsed_, "callback")); - EXPECT_TRUE(FindTraceEntry(trace_parsed_, "yes")); - EXPECT_FALSE(FindTraceEntry(trace_parsed_, "no")); - } - - void VerifyCollectedEvent(size_t i, - unsigned phase, - const std::string& category, - const std::string& name) { - EXPECT_EQ(phase, collected_events_phases_[i]); - EXPECT_EQ(category, collected_events_categories_[i]); - EXPECT_EQ(name, collected_events_names_[i]); - } - - std::vector<std::string> collected_events_categories_; - std::vector<std::string> collected_events_names_; - std::vector<unsigned char> collected_events_phases_; - std::vector<TimeTicks> collected_events_timestamps_; - - static TraceEventCallbackTest* s_instance; - static void Callback(TimeTicks timestamp, - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int num_args, - const char* const arg_names[], - const unsigned char arg_types[], - const unsigned long long arg_values[], - unsigned int flags) { - s_instance->collected_events_phases_.push_back(phase); - s_instance->collected_events_categories_.push_back( - TraceLog::GetCategoryGroupName(category_group_enabled)); - s_instance->collected_events_names_.push_back(name); - s_instance->collected_events_timestamps_.push_back(timestamp); - } -}; - -TraceEventCallbackTest* TraceEventCallbackTest::s_instance; - -TEST_F(TraceEventCallbackTest, TraceEventCallback) { - TRACE_EVENT_INSTANT0("all", "before enable", TRACE_EVENT_SCOPE_THREAD); - TraceLog::GetInstance()->SetEventCallbackEnabled( - TraceConfig(kRecordAllCategoryFilter, ""), Callback); - TRACE_EVENT_INSTANT0("all", "event1", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("all", "event2", TRACE_EVENT_SCOPE_GLOBAL); - { - TRACE_EVENT0("all", "duration"); - TRACE_EVENT_INSTANT0("all", "event3", TRACE_EVENT_SCOPE_GLOBAL); - } - TraceLog::GetInstance()->SetEventCallbackDisabled(); - TRACE_EVENT_INSTANT0("all", "after callback removed", - TRACE_EVENT_SCOPE_GLOBAL); - ASSERT_EQ(5u, collected_events_names_.size()); - EXPECT_EQ("event1", collected_events_names_[0]); - EXPECT_EQ(TRACE_EVENT_PHASE_INSTANT, collected_events_phases_[0]); - EXPECT_EQ("event2", collected_events_names_[1]); - EXPECT_EQ(TRACE_EVENT_PHASE_INSTANT, collected_events_phases_[1]); - EXPECT_EQ("duration", collected_events_names_[2]); - EXPECT_EQ(TRACE_EVENT_PHASE_BEGIN, collected_events_phases_[2]); - EXPECT_EQ("event3", collected_events_names_[3]); - EXPECT_EQ(TRACE_EVENT_PHASE_INSTANT, collected_events_phases_[3]); - EXPECT_EQ("duration", collected_events_names_[4]); - EXPECT_EQ(TRACE_EVENT_PHASE_END, collected_events_phases_[4]); - for (size_t i = 1; i < collected_events_timestamps_.size(); i++) { - EXPECT_LE(collected_events_timestamps_[i - 1], - collected_events_timestamps_[i]); - } -} - -TEST_F(TraceEventCallbackTest, TraceEventCallbackWhileFull) { - TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""), - TraceLog::RECORDING_MODE); - do { - TRACE_EVENT_INSTANT0("all", "badger badger", TRACE_EVENT_SCOPE_GLOBAL); - } while (!TraceLog::GetInstance()->BufferIsFull()); - TraceLog::GetInstance()->SetEventCallbackEnabled( - TraceConfig(kRecordAllCategoryFilter, ""), Callback); - TRACE_EVENT_INSTANT0("all", "a snake", TRACE_EVENT_SCOPE_GLOBAL); - TraceLog::GetInstance()->SetEventCallbackDisabled(); - ASSERT_EQ(1u, collected_events_names_.size()); - EXPECT_EQ("a snake", collected_events_names_[0]); -} - -// 1: Enable callback, enable recording, disable callback, disable recording. -TEST_F(TraceEventCallbackTest, TraceEventCallbackAndRecording1) { - TRACE_EVENT_INSTANT0("recording", "no", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("callback", "no", TRACE_EVENT_SCOPE_GLOBAL); - TraceLog::GetInstance()->SetEventCallbackEnabled(TraceConfig("callback", ""), - Callback); - TRACE_EVENT_INSTANT0("recording", "no", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("callback", "yes", TRACE_EVENT_SCOPE_GLOBAL); - TraceLog::GetInstance()->SetEnabled(TraceConfig("recording", ""), - TraceLog::RECORDING_MODE); - TRACE_EVENT_INSTANT0("recording", "yes", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("callback", "yes", TRACE_EVENT_SCOPE_GLOBAL); - TraceLog::GetInstance()->SetEventCallbackDisabled(); - TRACE_EVENT_INSTANT0("recording", "yes", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("callback", "no", TRACE_EVENT_SCOPE_GLOBAL); - EndTraceAndFlush(); - TRACE_EVENT_INSTANT0("recording", "no", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("callback", "no", TRACE_EVENT_SCOPE_GLOBAL); - - DropTracedMetadataRecords(); - VerifyCallbackAndRecordedEvents(2, 2); -} - -// 2: Enable callback, enable recording, disable recording, disable callback. -TEST_F(TraceEventCallbackTest, TraceEventCallbackAndRecording2) { - TRACE_EVENT_INSTANT0("recording", "no", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("callback", "no", TRACE_EVENT_SCOPE_GLOBAL); - TraceLog::GetInstance()->SetEventCallbackEnabled(TraceConfig("callback", ""), - Callback); - TRACE_EVENT_INSTANT0("recording", "no", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("callback", "yes", TRACE_EVENT_SCOPE_GLOBAL); - TraceLog::GetInstance()->SetEnabled(TraceConfig("recording", ""), - TraceLog::RECORDING_MODE); - TRACE_EVENT_INSTANT0("recording", "yes", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("callback", "yes", TRACE_EVENT_SCOPE_GLOBAL); - EndTraceAndFlush(); - TRACE_EVENT_INSTANT0("recording", "no", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("callback", "yes", TRACE_EVENT_SCOPE_GLOBAL); - TraceLog::GetInstance()->SetEventCallbackDisabled(); - TRACE_EVENT_INSTANT0("recording", "no", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("callback", "no", TRACE_EVENT_SCOPE_GLOBAL); - - DropTracedMetadataRecords(); - VerifyCallbackAndRecordedEvents(3, 1); -} - -// 3: Enable recording, enable callback, disable callback, disable recording. -TEST_F(TraceEventCallbackTest, TraceEventCallbackAndRecording3) { - TRACE_EVENT_INSTANT0("recording", "no", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("callback", "no", TRACE_EVENT_SCOPE_GLOBAL); - TraceLog::GetInstance()->SetEnabled(TraceConfig("recording", ""), - TraceLog::RECORDING_MODE); - TRACE_EVENT_INSTANT0("recording", "yes", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("callback", "no", TRACE_EVENT_SCOPE_GLOBAL); - TraceLog::GetInstance()->SetEventCallbackEnabled(TraceConfig("callback", ""), - Callback); - TRACE_EVENT_INSTANT0("recording", "yes", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("callback", "yes", TRACE_EVENT_SCOPE_GLOBAL); - TraceLog::GetInstance()->SetEventCallbackDisabled(); - TRACE_EVENT_INSTANT0("recording", "yes", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("callback", "no", TRACE_EVENT_SCOPE_GLOBAL); - EndTraceAndFlush(); - TRACE_EVENT_INSTANT0("recording", "no", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("callback", "no", TRACE_EVENT_SCOPE_GLOBAL); - - DropTracedMetadataRecords(); - VerifyCallbackAndRecordedEvents(1, 3); -} - -// 4: Enable recording, enable callback, disable recording, disable callback. -TEST_F(TraceEventCallbackTest, TraceEventCallbackAndRecording4) { - TRACE_EVENT_INSTANT0("recording", "no", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("callback", "no", TRACE_EVENT_SCOPE_GLOBAL); - TraceLog::GetInstance()->SetEnabled(TraceConfig("recording", ""), - TraceLog::RECORDING_MODE); - TRACE_EVENT_INSTANT0("recording", "yes", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("callback", "no", TRACE_EVENT_SCOPE_GLOBAL); - TraceLog::GetInstance()->SetEventCallbackEnabled(TraceConfig("callback", ""), - Callback); - TRACE_EVENT_INSTANT0("recording", "yes", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("callback", "yes", TRACE_EVENT_SCOPE_GLOBAL); - EndTraceAndFlush(); - TRACE_EVENT_INSTANT0("recording", "no", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("callback", "yes", TRACE_EVENT_SCOPE_GLOBAL); - TraceLog::GetInstance()->SetEventCallbackDisabled(); - TRACE_EVENT_INSTANT0("recording", "no", TRACE_EVENT_SCOPE_GLOBAL); - TRACE_EVENT_INSTANT0("callback", "no", TRACE_EVENT_SCOPE_GLOBAL); - - DropTracedMetadataRecords(); - VerifyCallbackAndRecordedEvents(2, 2); -} - -TEST_F(TraceEventCallbackTest, TraceEventCallbackAndRecordingDuration) { - TraceLog::GetInstance()->SetEventCallbackEnabled( - TraceConfig(kRecordAllCategoryFilter, ""), Callback); - { - TRACE_EVENT0("callback", "duration1"); - TraceLog::GetInstance()->SetEnabled( - TraceConfig(kRecordAllCategoryFilter, ""), TraceLog::RECORDING_MODE); - TRACE_EVENT0("callback", "duration2"); - EndTraceAndFlush(); - TRACE_EVENT0("callback", "duration3"); - } - TraceLog::GetInstance()->SetEventCallbackDisabled(); - - ASSERT_EQ(6u, collected_events_names_.size()); - VerifyCollectedEvent(0, TRACE_EVENT_PHASE_BEGIN, "callback", "duration1"); - VerifyCollectedEvent(1, TRACE_EVENT_PHASE_BEGIN, "callback", "duration2"); - VerifyCollectedEvent(2, TRACE_EVENT_PHASE_BEGIN, "callback", "duration3"); - VerifyCollectedEvent(3, TRACE_EVENT_PHASE_END, "callback", "duration3"); - VerifyCollectedEvent(4, TRACE_EVENT_PHASE_END, "callback", "duration2"); - VerifyCollectedEvent(5, TRACE_EVENT_PHASE_END, "callback", "duration1"); -} - TEST_F(TraceEventTestFixture, TraceBufferVectorReportFull) { TraceLog* trace_log = TraceLog::GetInstance(); trace_log->SetEnabled( @@ -3245,30 +3019,142 @@ public: bool FilterTraceEvent(const TraceEvent& trace_event) const override { filter_trace_event_hit_count_++; - return true; + return filter_return_value_; } void EndEvent(const char* category_group, const char* name) override { end_event_hit_count_++; } + static void set_filter_return_value(bool value) { + filter_return_value_ = value; + } + static size_t filter_trace_event_hit_count() { return filter_trace_event_hit_count_; } static size_t end_event_hit_count() { return end_event_hit_count_; } + static void clear_counts() { + filter_trace_event_hit_count_ = 0; + end_event_hit_count_ = 0; + } + private: static size_t filter_trace_event_hit_count_; static size_t end_event_hit_count_; + static bool filter_return_value_; }; size_t TestEventFilter::filter_trace_event_hit_count_ = 0; size_t TestEventFilter::end_event_hit_count_ = 0; +bool TestEventFilter::filter_return_value_ = false; std::unique_ptr<TraceLog::TraceEventFilter> ConstructTestEventFilter() { return WrapUnique(new TestEventFilter); } +TEST_F(TraceEventTestFixture, TraceFilteringMode) { + const char config_json[] = + "{" + " \"event_filters\": [" + " {" + " \"filter_predicate\": \"testing_predicate\", " + " \"included_categories\": [\"*\"]" + " }" + " ]" + "}"; + + // Run RECORDING_MODE within FILTERING_MODE: + TestEventFilter::set_filter_return_value(true); + TraceLog::SetTraceEventFilterConstructorForTesting(ConstructTestEventFilter); + + // Only filtering mode is enabled with test filters. + TraceLog::GetInstance()->SetEnabled(TraceConfig(config_json), + TraceLog::FILTERING_MODE); + EXPECT_EQ(TraceLog::FILTERING_MODE, TraceLog::GetInstance()->enabled_modes()); + { + void* ptr = this; + TRACE_EVENT0("c0", "name0"); + TRACE_EVENT_ASYNC_BEGIN0("c1", "name1", ptr); + TRACE_EVENT_INSTANT0("c0", "name0", TRACE_EVENT_SCOPE_THREAD); + TRACE_EVENT_ASYNC_END0("c1", "name1", ptr); + } + + // Recording mode is enabled when filtering mode is turned on. + TraceLog::GetInstance()->SetEnabled(TraceConfig("", ""), + TraceLog::RECORDING_MODE); + EXPECT_EQ(TraceLog::RECORDING_MODE | TraceLog::FILTERING_MODE, + TraceLog::GetInstance()->enabled_modes()); + { + TRACE_EVENT0("c2", "name2"); + } + // Only recording mode is disabled and filtering mode will continue to run. + TraceLog::GetInstance()->SetDisabled(TraceLog::RECORDING_MODE); + EXPECT_EQ(TraceLog::FILTERING_MODE, TraceLog::GetInstance()->enabled_modes()); + + { + TRACE_EVENT0("c0", "name0"); + } + // Filtering mode is disabled and no tracing mode should be enabled. + TraceLog::GetInstance()->SetDisabled(TraceLog::FILTERING_MODE); + EXPECT_EQ(0, TraceLog::GetInstance()->enabled_modes()); + + EndTraceAndFlush(); + EXPECT_FALSE(FindMatchingValue("cat", "c0")); + EXPECT_FALSE(FindMatchingValue("cat", "c1")); + EXPECT_FALSE(FindMatchingValue("name", "name0")); + EXPECT_FALSE(FindMatchingValue("name", "name1")); + EXPECT_TRUE(FindMatchingValue("cat", "c2")); + EXPECT_TRUE(FindMatchingValue("name", "name2")); + EXPECT_EQ(6u, TestEventFilter::filter_trace_event_hit_count()); + EXPECT_EQ(3u, TestEventFilter::end_event_hit_count()); + Clear(); + TestEventFilter::clear_counts(); + + // Run FILTERING_MODE within RECORDING_MODE: + // Only recording mode is enabled and all events must be recorded. + TraceLog::GetInstance()->SetEnabled(TraceConfig("", ""), + TraceLog::RECORDING_MODE); + EXPECT_EQ(TraceLog::RECORDING_MODE, TraceLog::GetInstance()->enabled_modes()); + { + TRACE_EVENT0("c0", "name0"); + } + + // Filtering mode is also enabled and all events must be filtered-out. + TestEventFilter::set_filter_return_value(false); + TraceLog::GetInstance()->SetEnabled(TraceConfig(config_json), + TraceLog::FILTERING_MODE); + EXPECT_EQ(TraceLog::RECORDING_MODE | TraceLog::FILTERING_MODE, + TraceLog::GetInstance()->enabled_modes()); + { + TRACE_EVENT0("c1", "name1"); + } + // Only filtering mode is disabled and recording mode should continue to run + // with all events being recorded. + TraceLog::GetInstance()->SetDisabled(TraceLog::FILTERING_MODE); + EXPECT_EQ(TraceLog::RECORDING_MODE, TraceLog::GetInstance()->enabled_modes()); + + { + TRACE_EVENT0("c2", "name2"); + } + // Recording mode is disabled and no tracing mode should be enabled. + TraceLog::GetInstance()->SetDisabled(TraceLog::RECORDING_MODE); + EXPECT_EQ(0, TraceLog::GetInstance()->enabled_modes()); + + EndTraceAndFlush(); + EXPECT_TRUE(FindMatchingValue("cat", "c0")); + EXPECT_TRUE(FindMatchingValue("cat", "c2")); + EXPECT_TRUE(FindMatchingValue("name", "name0")); + EXPECT_TRUE(FindMatchingValue("name", "name2")); + EXPECT_FALSE(FindMatchingValue("cat", "c1")); + EXPECT_FALSE(FindMatchingValue("name", "name1")); + EXPECT_EQ(1u, TestEventFilter::filter_trace_event_hit_count()); + EXPECT_EQ(1u, TestEventFilter::end_event_hit_count()); + Clear(); + TestEventFilter::clear_counts(); +} + TEST_F(TraceEventTestFixture, EventFiltering) { const char config_json[] = "{" @@ -3284,9 +3170,11 @@ " ]" "}"; + TestEventFilter::set_filter_return_value(true); TraceLog::SetTraceEventFilterConstructorForTesting(ConstructTestEventFilter); TraceConfig trace_config(config_json); - TraceLog::GetInstance()->SetEnabled(trace_config, TraceLog::RECORDING_MODE); + TraceLog::GetInstance()->SetEnabled( + trace_config, TraceLog::RECORDING_MODE | TraceLog::FILTERING_MODE); ASSERT_TRUE(TraceLog::GetInstance()->IsEnabled()); TRACE_EVENT0("filtered_cat", "a snake"); @@ -3300,6 +3188,7 @@ EXPECT_EQ(3u, TestEventFilter::filter_trace_event_hit_count()); EXPECT_EQ(1u, TestEventFilter::end_event_hit_count()); + TestEventFilter::clear_counts(); } TEST_F(TraceEventTestFixture, EventWhitelistFiltering) { @@ -3323,7 +3212,8 @@ TraceLog::TraceEventFilter::kEventWhitelistPredicate); TraceConfig trace_config(config_json); - TraceLog::GetInstance()->SetEnabled(trace_config, TraceLog::RECORDING_MODE); + TraceLog::GetInstance()->SetEnabled( + trace_config, TraceLog::RECORDING_MODE | TraceLog::FILTERING_MODE); EXPECT_TRUE(TraceLog::GetInstance()->IsEnabled()); TRACE_EVENT0("filtered_cat", "a snake"); @@ -3354,7 +3244,8 @@ TraceLog::TraceEventFilter::kHeapProfilerPredicate); TraceConfig trace_config(config_json); - TraceLog::GetInstance()->SetEnabled(trace_config, TraceLog::RECORDING_MODE); + TraceLog::GetInstance()->SetEnabled( + trace_config, TraceLog::RECORDING_MODE | TraceLog::FILTERING_MODE); EXPECT_TRUE(TraceLog::GetInstance()->IsEnabled()); TRACE_EVENT0("filtered_cat", "a snake");
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc index c56f5c78..9bb7a8a 100644 --- a/base/trace_event/trace_log.cc +++ b/base/trace_event/trace_log.cc
@@ -462,9 +462,8 @@ } TraceLog::TraceLog() - : mode_(DISABLED), + : enabled_modes_(0), num_traces_recorded_(0), - event_callback_(0), dispatching_to_observer_list_(false), process_sort_index_(0), process_id_hash_(0), @@ -472,7 +471,6 @@ watch_category_(0), trace_options_(kInternalRecordUntilFull), trace_config_(TraceConfig()), - event_callback_trace_config_(TraceConfig()), thread_shared_chunk_index_(0), generation_(0), use_worker_thread_(false) { @@ -560,16 +558,11 @@ void TraceLog::UpdateCategoryGroupEnabledFlag(size_t category_index) { unsigned char enabled_flag = 0; const char* category_group = g_category_groups[category_index]; - if (mode_ == RECORDING_MODE && + if (enabled_modes_ & RECORDING_MODE && trace_config_.IsCategoryGroupEnabled(category_group)) { enabled_flag |= ENABLED_FOR_RECORDING; } - if (event_callback_ && - event_callback_trace_config_.IsCategoryGroupEnabled(category_group)) { - enabled_flag |= ENABLED_FOR_EVENT_CALLBACK; - } - #if defined(OS_WIN) if (base::trace_event::TraceEventETWExport::IsCategoryGroupEnabled( category_group)) { @@ -580,12 +573,12 @@ // TODO(primiano): this is a temporary workaround for catapult:#2341, // to guarantee that metadata events are always added even if the category // filter is "-*". See crbug.com/618054 for more details and long-term fix. - if (mode_ == RECORDING_MODE && !strcmp(category_group, "__metadata")) + if (enabled_modes_ & RECORDING_MODE && !strcmp(category_group, "__metadata")) enabled_flag |= ENABLED_FOR_RECORDING; uint32_t enabled_filters_bitmap = 0; int index = 0; - for (const auto& event_filter : trace_config_.event_filters()) { + for (const auto& event_filter : enabled_event_filters_) { if (event_filter.IsCategoryGroupEnabled(category_group)) { enabled_flag |= ENABLED_FOR_FILTERING; DCHECK(g_category_group_filters.Get()[index]); @@ -609,12 +602,15 @@ } void TraceLog::CreateFiltersForTraceConfig() { + if (!(enabled_modes_ & FILTERING_MODE)) + return; + // Filters were already added and tracing could be enabled. Filters list // cannot be changed when trace events are using them. if (g_category_group_filters.Get().size()) return; - for (auto& event_filter : trace_config_.event_filters()) { + for (auto& event_filter : enabled_event_filters_) { if (g_category_group_filters.Get().size() >= MAX_TRACE_EVENT_FILTERS) { NOTREACHED() << "Too many trace event filters installed in the current session"; @@ -727,7 +723,8 @@ category_groups->push_back(g_category_groups[i]); } -void TraceLog::SetEnabled(const TraceConfig& trace_config, Mode mode) { +void TraceLog::SetEnabled(const TraceConfig& trace_config, + uint8_t modes_to_enable) { std::vector<EnabledStateObserver*> observer_list; std::map<AsyncEnabledStateObserver*, RegisteredAsyncObserver> observer_map; { @@ -741,32 +738,58 @@ InternalTraceOptions old_options = trace_options(); - if (IsEnabled()) { - if (new_options != old_options) { - DLOG(ERROR) << "Attempting to re-enable tracing with a different " - << "set of options."; - } - - if (mode != mode_) { - DLOG(ERROR) << "Attempting to re-enable tracing with a different mode."; - } - - DCHECK(!trace_config.event_filters().size()) - << "Adding new filters while tracing was already enabled is not " - "supported."; - - trace_config_.Merge(trace_config); - UpdateCategoryGroupEnabledFlags(); - return; - } - if (dispatching_to_observer_list_) { + // TODO(ssid): Change to NOTREACHED after fixing crbug.com/625170. DLOG(ERROR) << "Cannot manipulate TraceLog::Enabled state from an observer."; return; } - mode_ = mode; + // Clear all filters from previous tracing session. These filters are not + // cleared at the end of tracing because some threads which hit trace event + // when disabling, could try to use the filters. + if (!enabled_modes_) + g_category_group_filters.Get().clear(); + + // Update trace config for recording. + const bool already_recording = enabled_modes_ & RECORDING_MODE; + if (modes_to_enable & RECORDING_MODE) { + if (already_recording) { + // TODO(ssid): Stop suporting enabling of RECODING_MODE when already + // enabled crbug.com/625170. + DCHECK_EQ(new_options, old_options) << "Attempting to re-enable " + "tracing with a different set " + "of options."; + trace_config_.Merge(trace_config); + } else { + trace_config_ = trace_config; + } + } + + // Update event filters. + if (modes_to_enable & FILTERING_MODE) { + DCHECK(!trace_config.event_filters().empty()) + << "Attempting to enable filtering without any filters"; + DCHECK(enabled_event_filters_.empty()) << "Attempting to re-enable " + "filtering when filters are " + "already enabled."; + + // Use the given event filters only if filtering was not enabled. + if (enabled_event_filters_.empty()) + enabled_event_filters_ = trace_config.event_filters(); + } + // Keep the |trace_config_| updated with only enabled filters in case anyone + // tries to read it using |GetCurrentTraceConfig| (even if filters are + // empty). + trace_config_.SetEventFilters(enabled_event_filters_); + + enabled_modes_ |= modes_to_enable; + UpdateCategoryGroupEnabledFlags(); + + // Do not notify observers or create trace buffer if only enabled for + // filtering or if recording was already enabled. + if (!(modes_to_enable & RECORDING_MODE) || already_recording) + return; if (new_options != old_options) { subtle::NoBarrier_Store(&trace_options_, new_options); @@ -775,12 +798,6 @@ num_traces_recorded_++; - // Clear all filters from previous tracing session. These filters are not - // cleared at the end of tracing because some threads which hit trace event - // when disabling, could try to use the filters. - g_category_group_filters.Get().clear(); - - trace_config_ = TraceConfig(trace_config); UpdateCategoryGroupEnabledFlags(); UpdateSyntheticDelaysFromTraceConfig(); @@ -837,27 +854,48 @@ void TraceLog::SetDisabled() { AutoLock lock(lock_); - SetDisabledWhileLocked(); + SetDisabledWhileLocked(RECORDING_MODE); } -void TraceLog::SetDisabledWhileLocked() { +void TraceLog::SetDisabled(uint8_t modes_to_disable) { + AutoLock lock(lock_); + SetDisabledWhileLocked(modes_to_disable); +} + +void TraceLog::SetDisabledWhileLocked(uint8_t modes_to_disable) { lock_.AssertAcquired(); - if (!IsEnabled()) + if (!(enabled_modes_ & modes_to_disable)) return; if (dispatching_to_observer_list_) { + // TODO(ssid): Change to NOTREACHED after fixing crbug.com/625170. DLOG(ERROR) << "Cannot manipulate TraceLog::Enabled state from an observer."; return; } - mode_ = DISABLED; + bool is_recording_mode_disabled = + (enabled_modes_ & RECORDING_MODE) && (modes_to_disable & RECORDING_MODE); + enabled_modes_ &= ~modes_to_disable; - trace_config_.Clear(); - subtle::NoBarrier_Store(&watch_category_, 0); - watch_event_name_.clear(); + if (modes_to_disable & FILTERING_MODE) + enabled_event_filters_.clear(); + + if (modes_to_disable & RECORDING_MODE) { + trace_config_.Clear(); + + subtle::NoBarrier_Store(&watch_category_, 0); + watch_event_name_.clear(); + } + UpdateCategoryGroupEnabledFlags(); + + // Add metadata events and notify observers only if recording mode was + // disabled now. + if (!is_recording_mode_disabled) + return; + AddMetadataEventsWhileLocked(); // Remove metadata events so they will not get added to a subsequent trace. @@ -957,25 +995,10 @@ if (buffer_limit_reached_timestamp_.is_null()) { buffer_limit_reached_timestamp_ = OffsetNow(); } - SetDisabledWhileLocked(); + SetDisabledWhileLocked(RECORDING_MODE); } } -void TraceLog::SetEventCallbackEnabled(const TraceConfig& trace_config, - EventCallback cb) { - AutoLock lock(lock_); - subtle::NoBarrier_Store(&event_callback_, - reinterpret_cast<subtle::AtomicWord>(cb)); - event_callback_trace_config_ = trace_config; - UpdateCategoryGroupEnabledFlags(); -} - -void TraceLog::SetEventCallbackDisabled() { - AutoLock lock(lock_); - subtle::NoBarrier_Store(&event_callback_, 0); - UpdateCategoryGroupEnabledFlags(); -} - // Flush() works as the following: // 1. Flush() is called in thread A whose task runner is saved in // flush_task_runner_; @@ -1344,10 +1367,13 @@ TimeTicks offset_event_timestamp = OffsetTimestamp(timestamp); ThreadTicks thread_now = ThreadNow(); - // |thread_local_event_buffer_| can be null if the current thread doesn't have - // a message loop or the message loop is blocked. - InitializeThreadLocalEventBufferIfSupported(); - auto* thread_local_event_buffer = thread_local_event_buffer_.Get(); + ThreadLocalEventBuffer* thread_local_event_buffer = nullptr; + if (enabled_modes_ & RECORDING_MODE) { + // |thread_local_event_buffer_| can be null if the current thread doesn't + // have a message loop or the message loop is blocked. + InitializeThreadLocalEventBufferIfSupported(); + thread_local_event_buffer = thread_local_event_buffer_.Get(); + } // Check and update the current thread name only if the event is for the // current thread to avoid locks in most cases. @@ -1470,18 +1496,6 @@ } } - if (*category_group_enabled & ENABLED_FOR_EVENT_CALLBACK) { - EventCallback event_callback = reinterpret_cast<EventCallback>( - subtle::NoBarrier_Load(&event_callback_)); - if (event_callback) { - event_callback( - offset_event_timestamp, - phase == TRACE_EVENT_PHASE_COMPLETE ? TRACE_EVENT_PHASE_BEGIN : phase, - category_group_enabled, name, scope, id, num_args, arg_names, - arg_types, arg_values, flags); - } - } - return handle; } @@ -1629,17 +1643,6 @@ if (!console_message.empty()) LOG(ERROR) << console_message; - if (category_group_enabled_local & ENABLED_FOR_EVENT_CALLBACK) { - EventCallback event_callback = reinterpret_cast<EventCallback>( - subtle::NoBarrier_Load(&event_callback_)); - if (event_callback) { - event_callback( - now, TRACE_EVENT_PHASE_END, category_group_enabled, name, - trace_event_internal::kGlobalScope, trace_event_internal::kNoId, 0, - nullptr, nullptr, nullptr, TRACE_EVENT_FLAG_NONE); - } - } - if (category_group_enabled_local & ENABLED_FOR_FILTERING) EndFilteredEvent(category_group_enabled, name, handle); }
diff --git a/base/trace_event/trace_log.h b/base/trace_event/trace_log.h index d0759cd9..85fe153 100644 --- a/base/trace_event/trace_log.h +++ b/base/trace_event/trace_log.h
@@ -44,9 +44,14 @@ class BASE_EXPORT TraceLog : public MemoryDumpProvider { public: - enum Mode { - DISABLED = 0, - RECORDING_MODE + // Argument passed to TraceLog::SetEnabled. + enum Mode : uint8_t { + // Enables normal tracing (recording trace events in the trace buffer). + RECORDING_MODE = 1 << 0, + + // Trace events are enabled just for filtering but not for recording. Only + // event filters config of |trace_config| argument is used. + FILTERING_MODE = 1 << 1 }; // The pointer returned from GetCategoryGroupEnabledInternal() points to a @@ -56,8 +61,8 @@ enum CategoryGroupEnabledFlags { // Category group enabled for the recording mode. ENABLED_FOR_RECORDING = 1 << 0, - // Category group enabled by SetEventCallbackEnabled(). - ENABLED_FOR_EVENT_CALLBACK = 1 << 2, + // 1 << 2 was used for ENABLED_FOR_EVENT_CALLBACK. + // Category group enabled to export events to ETW. ENABLED_FOR_ETW_EXPORT = 1 << 3, // Category group being filtered before logged. @@ -77,16 +82,30 @@ // if the current thread supports that (has a message loop). void InitializeThreadLocalEventBufferIfSupported(); - // Enables normal tracing (recording trace events in the trace buffer). - // See TraceConfig comments for details on how to control what categories - // will be traced. If tracing has already been enabled, |category_filter| will - // be merged into the current category filter. - void SetEnabled(const TraceConfig& trace_config, Mode mode); + // See TraceConfig comments for details on how to control which categories + // will be traced. SetDisabled must be called distinctly for each mode that is + // enabled. If tracing has already been enabled for recording, category filter + // (enabled and disabled categories) will be merged into the current category + // filter. Enabling RECORDING_MODE does not enable filters. Trace event + // filters will be used only if FILTERING_MODE is set on |modes_to_enable|. + // Conversely to RECORDING_MODE, FILTERING_MODE doesn't support upgrading, + // i.e. filters can only be enabled if not previously enabled. + void SetEnabled(const TraceConfig& trace_config, uint8_t modes_to_enable); - // Disables normal tracing for all categories. + // TODO(ssid): Remove the default SetEnabled and IsEnabled. They should take + // Mode as argument. + + // Disables tracing for all categories for the specified |modes_to_disable| + // only. Only RECORDING_MODE is taken as default |modes_to_disable|. void SetDisabled(); + void SetDisabled(uint8_t modes_to_disable); - bool IsEnabled() { return mode_ != DISABLED; } + // Returns true if TraceLog is enabled on recording mode. + // Note: Returns false even if FILTERING_MODE is enabled. + bool IsEnabled() { return enabled_modes_ & RECORDING_MODE; } + + // Returns a bitmap of enabled modes from TraceLog::Mode. + uint8_t enabled_modes() { return enabled_modes_; } // The number of times we have begun recording traces. If tracing is off, // returns -1. If tracing is on, then it returns the number of times we have @@ -149,31 +168,6 @@ // objects. void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead); - // Not using base::Callback because of its limited by 7 parameters. - // Also, using primitive type allows directly passing callback from WebCore. - // WARNING: It is possible for the previously set callback to be called - // after a call to SetEventCallbackEnabled() that replaces or a call to - // SetEventCallbackDisabled() that disables the callback. - // This callback may be invoked on any thread. - // For TRACE_EVENT_PHASE_COMPLETE events, the client will still receive pairs - // of TRACE_EVENT_PHASE_BEGIN and TRACE_EVENT_PHASE_END events to keep the - // interface simple. - typedef void (*EventCallback)(TimeTicks timestamp, - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int num_args, - const char* const arg_names[], - const unsigned char arg_types[], - const unsigned long long arg_values[], - unsigned int flags); - - // Enable tracing for EventCallback. - void SetEventCallbackEnabled(const TraceConfig& trace_config, - EventCallback cb); - void SetEventCallbackDisabled(); void SetArgumentFilterPredicate( const ArgumentFilterPredicate& argument_filter_predicate); @@ -393,10 +387,10 @@ ProcessMemoryDump* pmd) override; // Enable/disable each category group based on the current mode_, - // category_filter_, event_callback_ and event_callback_category_filter_. - // Enable the category group in the enabled mode if category_filter_ matches - // the category group, or event_callback_ is not null and - // event_callback_category_filter_ matches the category group. + // category_filter_ and event_filters_enabled_. + // Enable the category group in the recording mode if category_filter_ matches + // the category group, is not null. Enable category for filtering if any + // filter in event_filters_enabled_ enables it. void UpdateCategoryGroupEnabledFlags(); void UpdateCategoryGroupEnabledFlag(size_t category_index); @@ -433,7 +427,7 @@ TraceEvent* AddEventToThreadSharedChunkWhileLocked(TraceEventHandle* handle, bool check_buffer_is_full); void CheckIfBufferIsFullWhileLocked(); - void SetDisabledWhileLocked(); + void SetDisabledWhileLocked(uint8_t modes); TraceEvent* GetEventByHandleInternal(TraceEventHandle handle, OptionalAutoLock* lock); @@ -481,11 +475,10 @@ // This lock protects accesses to thread_names_, thread_event_start_times_ // and thread_colors_. Lock thread_info_lock_; - Mode mode_; + uint8_t enabled_modes_; // See TraceLog::Mode. int num_traces_recorded_; std::unique_ptr<TraceBuffer> logged_events_; std::vector<std::unique_ptr<TraceEvent>> metadata_events_; - subtle::AtomicWord /* EventCallback */ event_callback_; bool dispatching_to_observer_list_; std::vector<EnabledStateObserver*> enabled_state_observer_list_; std::map<AsyncEnabledStateObserver*, RegisteredAsyncObserver> @@ -518,7 +511,7 @@ subtle::AtomicWord /* Options */ trace_options_; TraceConfig trace_config_; - TraceConfig event_callback_trace_config_; + TraceConfig::EventFilters enabled_event_filters_; ThreadLocalPointer<ThreadLocalEventBuffer> thread_local_event_buffer_; ThreadLocalBoolean thread_blocks_message_loop_;
diff --git a/build/android/generate_emma_html.py b/build/android/generate_emma_html.py index 9d1d7330..34121fd 100755 --- a/build/android/generate_emma_html.py +++ b/build/android/generate_emma_html.py
@@ -69,8 +69,21 @@ sources_file = os.path.splitext(f)[0] + '_sources.txt' with open(sources_file, 'r') as sf: sources.extend(json.load(sf)) - sources = [os.path.join(host_paths.DIR_SOURCE_ROOT, s) for s in sources] - print 'Sources: %s' % sources + + # Source paths should be passed to EMMA in a way that the relative file paths + # reflect the class package name. + PARTIAL_PACKAGE_NAMES = ['com/google', 'org/chromium', 'com/chrome'] + fixed_source_paths = set() + + for path in sources: + for partial in PARTIAL_PACKAGE_NAMES: + if partial in path: + fixed_path = os.path.join( + host_paths.DIR_SOURCE_ROOT, path[:path.index(partial)]) + fixed_source_paths.add(fixed_path) + break + + sources = list(fixed_source_paths) input_args = [] for f in coverage_files + metadata_files:
diff --git a/build/config/mac/mac_sdk.gni b/build/config/mac/mac_sdk.gni index 13837626..0fb5dd51 100644 --- a/build/config/mac/mac_sdk.gni +++ b/build/config/mac/mac_sdk.gni
@@ -3,6 +3,7 @@ # found in the LICENSE file. import("//build/config/chrome_build.gni") +import("//build/toolchain/toolchain.gni") # See https://bugs.chromium.org/p/webrtc/issues/detail?id=5453. # We can drop the rtc_require_mac_10_7_deployment flag when Chromium @@ -38,6 +39,12 @@ _verify_sdk = is_chrome_branded && is_official_build && target_os != "ios" find_sdk_args = [ "--print_sdk_path" ] +if (!use_system_xcode) { + find_sdk_args += [ + "--developer_dir", + hermetic_xcode_path, + ] +} if (_verify_sdk) { find_sdk_args += [ "--verify", @@ -58,8 +65,16 @@ } script_name = "//build/config/mac/sdk_info.py" -_mac_sdk_result = exec_script(script_name, [ mac_sdk_name ], "scope") -mac_sdk_build = _mac_sdk_result.sdk_build +sdk_info_args = [] +if (!use_system_xcode) { + sdk_info_args += [ + "--developer_dir", + hermetic_xcode_path, + ] +} +sdk_info_args += [ mac_sdk_name ] + +_mac_sdk_result = exec_script(script_name, sdk_info_args, "scope") xcode_version = _mac_sdk_result.xcode_version xcode_build = _mac_sdk_result.xcode_build machine_os_build = _mac_sdk_result.machine_os_build
diff --git a/build/config/mac/rules.gni b/build/config/mac/rules.gni index e3270a2..c10cc4b7 100644 --- a/build/config/mac/rules.gni +++ b/build/config/mac/rules.gni
@@ -43,7 +43,7 @@ extra_substitutions = invoker.extra_substitutions } extra_substitutions += [ - "MAC_SDK_BUILD=$mac_sdk_build", + "MAC_SDK_BUILD=$mac_sdk_version", "MAC_SDK_NAME=$mac_sdk_name$mac_sdk_version", ] plist_templates = [
diff --git a/build/config/mac/sdk_info.py b/build/config/mac/sdk_info.py index 52b2524..e63ac0bd 100644 --- a/build/config/mac/sdk_info.py +++ b/build/config/mac/sdk_info.py
@@ -2,13 +2,11 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import argparse import os import subprocess import sys -sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))) -import mac_toolchain - # This script prints information about the build system, the operating # system and the iOS or Mac SDK (depending on the platform "iphonesimulator", # "iphoneos" or "macosx" generally). @@ -54,19 +52,22 @@ if __name__ == '__main__': - if len(sys.argv) != 2: + parser = argparse.ArgumentParser() + parser.add_argument("--developer_dir", required=False) + args, unknownargs = parser.parse_known_args() + if args.developer_dir: + os.environ['DEVELOPER_DIR'] = args.developer_dir + + if len(unknownargs) != 1: sys.stderr.write( 'usage: %s [iphoneos|iphonesimulator|macosx]\n' % os.path.basename(sys.argv[0])) sys.exit(1) - # Try using the toolchain in mac_files. - mac_toolchain.SetToolchainEnvironment() - settings = {} FillMachineOSBuild(settings) FillXcodeVersion(settings) - FillSDKPathAndVersion(settings, sys.argv[1], settings['xcode_version']) + FillSDKPathAndVersion(settings, unknownargs[0], settings['xcode_version']) for key in sorted(settings): print '%s="%s"' % (key, settings[key])
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn index 9b6ac7423..ebcbb10 100644 --- a/build/config/win/BUILD.gn +++ b/build/config/win/BUILD.gn
@@ -264,6 +264,17 @@ } } +# Control Flow Guard (CFG) +# https://msdn.microsoft.com/en-us/library/windows/desktop/mt637065.aspx +config("win_msvc_cfg") { + # /DYNAMICBASE (ASLR) is turned off in debug builds, therefore CFG can’t be + # turned on either. + if (!is_clang && !is_debug) { + cflags = [ "/guard:cf" ] + ldflags = [ "/guard:cf" ] + } +} + # CRT -------------------------------------------------------------------------- # Configures how the runtime library (CRT) is going to be used.
diff --git a/build/gyp_environment.py b/build/gyp_environment.py index 87e3ea8..51b9136 100644 --- a/build/gyp_environment.py +++ b/build/gyp_environment.py
@@ -9,7 +9,6 @@ """ import gyp_helper -import mac_toolchain import os import sys import vs_toolchain @@ -29,4 +28,3 @@ os.environ['GYP_GENERATORS'] = 'ninja' vs_toolchain.SetEnvironmentAndGetRuntimeDllDirs() - mac_toolchain.SetToolchainEnvironment()
diff --git a/build/mac/find_sdk.py b/build/mac/find_sdk.py index f06fd15c..5172df3 100755 --- a/build/mac/find_sdk.py +++ b/build/mac/find_sdk.py
@@ -4,10 +4,11 @@ # found in the LICENSE file. """Prints the lowest locally available SDK version greater than or equal to a -given minimum sdk version to standard output. +given minimum sdk version to standard output. If --developer_dir is passed, then +the script will use the Xcode toolchain located at DEVELOPER_DIR. Usage: - python find_sdk.py 10.6 # Ignores SDKs < 10.6 + python find_sdk.py [--developer_dir DEVELOPER_DIR] 10.6 # Ignores SDKs < 10.6 """ import os @@ -15,9 +16,6 @@ import subprocess import sys -sys.path.append(os.path.dirname(os.path.dirname(__file__))) -import mac_toolchain - from optparse import OptionParser @@ -37,13 +35,14 @@ parser.add_option("--print_sdk_path", action="store_true", dest="print_sdk_path", default=False, help="Additionaly print the path the SDK (appears first).") + parser.add_option("--developer_dir", help='Path to Xcode.') options, args = parser.parse_args() if len(args) != 1: parser.error('Please specify a minimum SDK version') min_sdk_version = args[0] - # Try using the toolchain in mac_files. - mac_toolchain.SetToolchainEnvironment() + if options.developer_dir: + os.environ['DEVELOPER_DIR'] = options.developer_dir job = subprocess.Popen(['xcode-select', '-print-path'], stdout=subprocess.PIPE,
diff --git a/build/mac_toolchain.py b/build/mac_toolchain.py index 44ea7e6..5728ab5 100755 --- a/build/mac_toolchain.py +++ b/build/mac_toolchain.py
@@ -39,19 +39,6 @@ TOOLCHAIN_URL = 'gs://chrome-mac-sdk/' -def GetToolchainDirectory(): - if sys.platform == 'darwin' and not UseLocalMacSDK(): - return TOOLCHAIN_BUILD_DIR - else: - return None - - -def SetToolchainEnvironment(): - mac_toolchain_dir = GetToolchainDirectory() - if mac_toolchain_dir: - os.environ['DEVELOPER_DIR'] = mac_toolchain_dir - - def ReadStampFile(): """Return the contents of the stamp file, or '' if it doesn't exist.""" try: @@ -151,7 +138,7 @@ subprocess.check_call(['sudo', '/usr/bin/xcode-select', '-s', old_path]) -def UseLocalMacSDK(): +def _UseLocalMacSDK(): force_pull = os.environ.has_key('FORCE_MAC_TOOLCHAIN') # Don't update the toolchain if there's already one installed outside of the @@ -167,8 +154,7 @@ if sys.platform != 'darwin': return 0 - # TODO(justincohen): Add support for GN per crbug.com/570091 - if UseLocalMacSDK(): + if _UseLocalMacSDK(): print 'Using local toolchain.' return 0
diff --git a/cc/blimp/layer_tree_host_remote.cc b/cc/blimp/layer_tree_host_remote.cc index f4136c0..45ab48ef 100644 --- a/cc/blimp/layer_tree_host_remote.cc +++ b/cc/blimp/layer_tree_host_remote.cc
@@ -5,6 +5,7 @@ #include "cc/blimp/layer_tree_host_remote.h" #include "base/atomic_sequence_num.h" +#include "base/auto_reset.h" #include "base/memory/ptr_util.h" #include "cc/animation/animation_host.h" #include "cc/blimp/compositor_proto_state.h" @@ -19,6 +20,7 @@ #include "cc/trees/layer_tree_host_client.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/task_runner_provider.h" +#include "ui/gfx/geometry/scroll_offset.h" namespace cc { namespace { @@ -161,7 +163,11 @@ } bool LayerTreeHostRemote::CommitRequested() const { - return requested_pipeline_stage_for_next_frame_ == FramePipelineStage::COMMIT; + // We report that a commit is in progress when synchronizing scroll and scale + // updates because in threaded mode, scroll/scale synchronization from the + // impl thread happens only during the main frame. + return synchronizing_client_updates_ || + requested_pipeline_stage_for_next_frame_ == FramePipelineStage::COMMIT; } void LayerTreeHostRemote::SetDeferCommits(bool defer_commits) { @@ -412,6 +418,48 @@ weak_factory_.GetWeakPtr())); } +bool LayerTreeHostRemote::ApplyScrollAndScaleUpdateFromClient( + const ScrollOffsetMap& client_scroll_map, + float client_page_scale) { + DCHECK(!synchronizing_client_updates_); + + base::AutoReset<bool> synchronizing_updates(&synchronizing_client_updates_, + true); + bool layer_sync_successful = true; + + gfx::Vector2dF inner_viewport_scroll_delta; + Layer* inner_viewport_scroll_layer = + layer_tree_->inner_viewport_scroll_layer(); + for (const auto& client_scroll : client_scroll_map) { + Layer* layer = layer_tree_->LayerById(client_scroll.first); + const gfx::ScrollOffset& scroll_offset = client_scroll.second; + + // Note the inner viewport scroll delta to report separately. + if (layer == inner_viewport_scroll_layer) { + inner_viewport_scroll_delta = + scroll_offset.DeltaFrom(layer->scroll_offset()); + } + + if (layer) + layer->SetScrollOffsetFromImplSide(scroll_offset); + else + layer_sync_successful = false; + } + + float page_scale_delta = 1.0f; + if (client_page_scale != layer_tree_->page_scale_factor()) { + page_scale_delta = client_page_scale / layer_tree_->page_scale_factor(); + layer_tree_->SetPageScaleFromImplSide(client_page_scale); + } + + if (!inner_viewport_scroll_delta.IsZero() || page_scale_delta != 1.0f) { + client_->ApplyViewportDeltas(inner_viewport_scroll_delta, gfx::Vector2dF(), + gfx::Vector2dF(), page_scale_delta, 1.0f); + } + + return layer_sync_successful; +} + void LayerTreeHostRemote::MainFrameComplete() { DCHECK_EQ(current_pipeline_stage_, FramePipelineStage::COMMIT);
diff --git a/cc/blimp/layer_tree_host_remote.h b/cc/blimp/layer_tree_host_remote.h index 5ce5f169..e4ebc7c 100644 --- a/cc/blimp/layer_tree_host_remote.h +++ b/cc/blimp/layer_tree_host_remote.h
@@ -112,6 +112,9 @@ // RemoteCompositorBridgeClient implementation. void BeginMainFrame() override; + bool ApplyScrollAndScaleUpdateFromClient( + const ScrollOffsetMap& client_scroll_map, + float client_page_scale) override; private: enum class FramePipelineStage { NONE, ANIMATE, UPDATE_LAYERS, COMMIT }; @@ -126,6 +129,12 @@ bool visible_ = false; bool defer_commits_ = false; + // In threaded/single-threaded mode, the LayerTree and Layers expect scroll/ + // scale updates to come from the impl thread only during the main frame. + // Since we synchronize state outside of that, this is set so we can + // temporarily report that a commit is in progress. + bool synchronizing_client_updates_ = false; + // Set to true if a main frame request is pending on the // RemoteCompositorBridge. bool main_frame_requested_from_bridge_ = false;
diff --git a/cc/blimp/layer_tree_host_remote_unittest.cc b/cc/blimp/layer_tree_host_remote_unittest.cc index 03cdc74e..92822d8 100644 --- a/cc/blimp/layer_tree_host_remote_unittest.cc +++ b/cc/blimp/layer_tree_host_remote_unittest.cc
@@ -50,6 +50,11 @@ num_updates_received_++; }; + bool SendUpdates(const std::unordered_map<int, gfx::ScrollOffset>& scroll_map, + float page_scale) { + return client_->ApplyScrollAndScaleUpdateFromClient(scroll_map, page_scale); + } + int num_updates_received() const { return num_updates_received_; } private: @@ -79,6 +84,12 @@ MOCK_METHOD0(DidBeginMainFrame, void()); MOCK_METHOD0(DidReceiveBeginMainFrame, void()); MOCK_METHOD0(DidUpdateLayerTreeHost, void()); + MOCK_METHOD5(ApplyViewportDeltas, + void(const gfx::Vector2dF&, + const gfx::Vector2dF&, + const gfx::Vector2dF&, + float, + float)); MOCK_METHOD0(WillCommit, void()); MOCK_METHOD0(DidCommit, void()); MOCK_METHOD0(DidCommitAndDrawFrame, void()); @@ -347,5 +358,60 @@ EXPECT_EQ(1, remote_compositor_bridge_->num_updates_received()); } +TEST_F(LayerTreeHostRemoteTest, ScrollAndScaleSync) { + scoped_refptr<Layer> child_layer1 = make_scoped_refptr(new MockLayer(false)); + root_layer_->AddChild(child_layer1); + + scoped_refptr<Layer> child_layer2 = make_scoped_refptr(new MockLayer(false)); + child_layer1->AddChild(child_layer2); + + scoped_refptr<Layer> inner_viewport_layer = + make_scoped_refptr(new MockLayer(false)); + inner_viewport_layer->SetScrollOffset(gfx::ScrollOffset(5, 10)); + root_layer_->AddChild(inner_viewport_layer); + layer_tree_host_->GetLayerTree()->RegisterViewportLayers( + nullptr, nullptr, inner_viewport_layer, nullptr); + + // Send scroll and scale updates from client. + std::unordered_map<int, gfx::ScrollOffset> scroll_updates; + gfx::ScrollOffset child1_offset(4, 5); + gfx::ScrollOffset child2_offset(3, 10); + gfx::Vector2dF inner_viewport_delta(-2, 5); + gfx::ScrollOffset inner_viewport_offset = gfx::ScrollOffsetWithDelta( + inner_viewport_layer->scroll_offset(), inner_viewport_delta); + scroll_updates[child_layer1->id()] = child1_offset; + scroll_updates[child_layer2->id()] = child2_offset; + scroll_updates[inner_viewport_layer->id()] = inner_viewport_offset; + + float page_scale_delta = 0.3f; + float current_scale_factor = 0.5f; + layer_tree_host_->GetLayerTree()->SetPageScaleFactorAndLimits( + current_scale_factor, 0.0f, 1.0f); + float new_scale_factor = current_scale_factor * page_scale_delta; + + EXPECT_CALL(mock_layer_tree_host_client_, + ApplyViewportDeltas(inner_viewport_delta, gfx::Vector2dF(), + gfx::Vector2dF(), page_scale_delta, 1.0f)) + .Times(1); + bool updates_applied = + remote_compositor_bridge_->SendUpdates(scroll_updates, new_scale_factor); + EXPECT_TRUE(updates_applied); + // The host should have pre-emtively applied the changes. + EXPECT_EQ(new_scale_factor, + layer_tree_host_->GetLayerTree()->page_scale_factor()); + EXPECT_EQ(child1_offset, child_layer1->scroll_offset()); + EXPECT_EQ(child2_offset, child_layer2->scroll_offset()); + EXPECT_EQ(inner_viewport_offset, inner_viewport_layer->scroll_offset()); + + // Destroy a layer and send a scroll update for it. We should be informed that + // the update could not be applied successfully. + child_layer1->RemoveAllChildren(); + scroll_updates.clear(); + scroll_updates[child_layer2->id()] = gfx::ScrollOffset(3, 2); + updates_applied = + remote_compositor_bridge_->SendUpdates(scroll_updates, new_scale_factor); + EXPECT_FALSE(updates_applied); +} + } // namespace } // namespace cc
diff --git a/cc/blimp/remote_compositor_bridge_client.h b/cc/blimp/remote_compositor_bridge_client.h index 434dd0ab..1df4e0af 100644 --- a/cc/blimp/remote_compositor_bridge_client.h +++ b/cc/blimp/remote_compositor_bridge_client.h
@@ -5,6 +5,8 @@ #ifndef CC_BLIMP_REMOTE_COMPOSITOR_BRIDGE_CLIENT_H_ #define CC_BLIMP_REMOTE_COMPOSITOR_BRIDGE_CLIENT_H_ +#include <unordered_map> + #include "base/macros.h" #include "cc/base/cc_export.h" @@ -12,11 +14,17 @@ class SingleThreadTaskRunner; } // namespace base +namespace gfx { +class ScrollOffset; +} // namespace gfx + namespace cc { class CompositorProtoState; class CC_EXPORT RemoteCompositorBridgeClient { public: + using ScrollOffsetMap = std::unordered_map<int, gfx::ScrollOffset>; + virtual ~RemoteCompositorBridgeClient() {} // Called in response to a ScheduleMainFrame request made on the @@ -24,6 +32,14 @@ // Note: The method should always be invoked asynchronously after the request // is made. virtual void BeginMainFrame() = 0; + + // Provides an update from the mutations made on the client. Returns true if + // the update could be successfully applied to the engine state. This can + // fail, for instance, if the layer present in the update was destroyed on the + // engine. + virtual bool ApplyScrollAndScaleUpdateFromClient( + const ScrollOffsetMap& client_scroll_map, + float client_page_scale) = 0; }; } // namespace cc
diff --git a/cc/layers/layer.h b/cc/layers/layer.h index d0bd07c..42af680 100644 --- a/cc/layers/layer.h +++ b/cc/layers/layer.h
@@ -206,7 +206,6 @@ void SetScrollParent(Layer* parent); Layer* scroll_parent() { return inputs_.scroll_parent; } - const Layer* scroll_parent() const { return inputs_.scroll_parent; } std::set<Layer*>* scroll_children() { return scroll_children_.get(); } const std::set<Layer*>* scroll_children() const { @@ -216,7 +215,6 @@ void SetClipParent(Layer* ancestor); Layer* clip_parent() { return inputs_.clip_parent; } - const Layer* clip_parent() const { return inputs_.clip_parent; } std::set<Layer*>* clip_children() { return clip_children_.get(); } const std::set<Layer*>* clip_children() const { @@ -318,8 +316,6 @@ void SetFiltersOrigin(const gfx::PointF& origin); gfx::PointF filters_origin() const { return inputs_.filters_origin; } - bool has_mask() const { return !!inputs_.mask_layer.get(); } - int NumDescendantsThatDrawContent() const; // This is only virtual for tests. @@ -460,8 +456,6 @@ visible_layer_rect_ = rect; } - void set_clip_rect(const gfx::Rect& rect) {} - void SetSubtreePropertyChanged(); bool subtree_property_changed() const { return subtree_property_changed_; } @@ -499,7 +493,6 @@ Layer(); LayerTreeHost* layer_tree_host() { return layer_tree_host_; } - const LayerTreeHost* layer_tree_host() const { return layer_tree_host_; } // These SetNeeds functions are in order of severity of update: //
diff --git a/cc/resources/scoped_ui_resource.h b/cc/resources/scoped_ui_resource.h index 14db076b..7f3ea4b 100644 --- a/cc/resources/scoped_ui_resource.h +++ b/cc/resources/scoped_ui_resource.h
@@ -32,6 +32,11 @@ UIResourceBitmap GetBitmap(UIResourceId uid, bool resource_lost) override; UIResourceId id() { return id_; } + // Returns the memory usage of the bitmap. + size_t GetAllocatedSizeInBytes() const { + return bitmap_.GetAllocatedSizeInBytes(); + } + protected: ScopedUIResource(UIResourceManager* ui_resource_manager, const UIResourceBitmap& bitmap);
diff --git a/cc/resources/ui_resource_bitmap.h b/cc/resources/ui_resource_bitmap.h index 23492182..6f2c780 100644 --- a/cc/resources/ui_resource_bitmap.h +++ b/cc/resources/ui_resource_bitmap.h
@@ -51,6 +51,11 @@ UIResourceBitmap(const UIResourceBitmap& other); ~UIResourceBitmap(); + // Returns the memory usage of the bitmap. + size_t GetAllocatedSizeInBytes() const { + return pixel_ref_ ? pixel_ref_->rowBytes() * size_.height() : 0; + } + private: friend class AutoLockUIResourceBitmap;
diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc index b54be557..9fe434f 100644 --- a/cc/resources/video_resource_updater.cc +++ b/cc/resources/video_resource_updater.cc
@@ -61,6 +61,7 @@ case media::PIXEL_FORMAT_NV12: switch (video_frame->mailbox_holder(0).texture_target) { case GL_TEXTURE_EXTERNAL_OES: + case GL_TEXTURE_2D: return VideoFrameExternalResources::YUV_RESOURCE; case GL_TEXTURE_RECTANGLE_ARB: return VideoFrameExternalResources::RGB_RESOURCE;
diff --git a/cc/surfaces/surface_manager.cc b/cc/surfaces/surface_manager.cc index c627b033..0e204a4 100644 --- a/cc/surfaces/surface_manager.cc +++ b/cc/surfaces/surface_manager.cc
@@ -345,8 +345,8 @@ bool SurfaceManager::SurfaceModified(const SurfaceId& surface_id) { CHECK(thread_checker_.CalledOnValidThread()); bool changed = false; - FOR_EACH_OBSERVER(SurfaceObserver, observer_list_, - OnSurfaceDamaged(surface_id, &changed)); + for (auto& observer : observer_list_) + observer.OnSurfaceDamaged(surface_id, &changed); return changed; } @@ -354,9 +354,8 @@ const gfx::Size& frame_size, float device_scale_factor) { CHECK(thread_checker_.CalledOnValidThread()); - FOR_EACH_OBSERVER( - SurfaceObserver, observer_list_, - OnSurfaceCreated(surface_id, frame_size, device_scale_factor)); + for (auto& observer : observer_list_) + observer.OnSurfaceCreated(surface_id, frame_size, device_scale_factor); } } // namespace cc
diff --git a/cc/test/fake_remote_compositor_bridge.h b/cc/test/fake_remote_compositor_bridge.h index 5958f36..698dbed2 100644 --- a/cc/test/fake_remote_compositor_bridge.h +++ b/cc/test/fake_remote_compositor_bridge.h
@@ -28,7 +28,7 @@ void ProcessCompositorStateUpdate( std::unique_ptr<CompositorProtoState> compositor_proto_state) override {} - private: + protected: void BeginMainFrame(); RemoteCompositorBridgeClient* client_;
diff --git a/cc/test/layer_tree_host_remote_for_testing.cc b/cc/test/layer_tree_host_remote_for_testing.cc index ff877df3..25dc9e57 100644 --- a/cc/test/layer_tree_host_remote_for_testing.cc +++ b/cc/test/layer_tree_host_remote_for_testing.cc
@@ -9,6 +9,7 @@ #include "cc/blimp/compositor_proto_state.h" #include "cc/blimp/compositor_state_deserializer.h" #include "cc/blimp/remote_compositor_bridge.h" +#include "cc/layers/layer.h" #include "cc/proto/compositor_message.pb.h" #include "cc/test/fake_image_serialization_processor.h" #include "cc/test/remote_client_layer_factory.h" @@ -61,6 +62,8 @@ void WillBeginMainFrame() override {} void BeginMainFrame(const BeginFrameArgs& args) override { + // Send any scroll/scale updates first. + layer_tree_host_remote_->ApplyUpdatesFromInProcessHost(); layer_tree_host_remote_->BeginMainFrame(); } void BeginMainFrameNotExpectedSoon() override {} @@ -72,9 +75,7 @@ const gfx::Vector2dF& outer_delta, const gfx::Vector2dF& elastic_overscroll_delta, float page_scale, - float top_controls_delta) override { - // TODO(khushalsagar): Hook up when scroll/scale sync is added. - } + float top_controls_delta) override {} void RequestNewCompositorFrameSink() override { layer_tree_host_remote_->client()->RequestNewCompositorFrameSink(); } @@ -276,7 +277,16 @@ } void LayerTreeHostRemoteForTesting::LayerDidScroll(int engine_layer_id) { - // TODO(khushalsagar): Hook up when scroll/scale sync is added. + layers_scrolled_[engine_layer_id] = + compositor_state_deserializer_->GetLayerForEngineId(engine_layer_id) + ->scroll_offset(); +} + +void LayerTreeHostRemoteForTesting::ApplyUpdatesFromInProcessHost() { + ApplyScrollAndScaleUpdateFromClient( + layers_scrolled_, + layer_tree_host_in_process_->GetLayerTree()->page_scale_factor()); + layers_scrolled_.clear(); } void LayerTreeHostRemoteForTesting::RemoteHostNeedsMainFrame() {
diff --git a/cc/test/layer_tree_host_remote_for_testing.h b/cc/test/layer_tree_host_remote_for_testing.h index 9220b96..1ea328e 100644 --- a/cc/test/layer_tree_host_remote_for_testing.h +++ b/cc/test/layer_tree_host_remote_for_testing.h
@@ -8,6 +8,7 @@ #include "base/macros.h" #include "cc/blimp/compositor_state_deserializer_client.h" #include "cc/blimp/layer_tree_host_remote.h" +#include "ui/gfx/geometry/scroll_offset.h" namespace gpu { class GpuMemoryBufferManager; @@ -89,6 +90,7 @@ void DispatchDrawAndSwapCallbacks() override; void LayerDidScroll(int engine_layer_id); + void ApplyUpdatesFromInProcessHost(); void RemoteHostNeedsMainFrame(); void ProcessRemoteCompositorUpdate( @@ -99,6 +101,7 @@ std::unique_ptr<CompositorStateDeserializer> compositor_state_deserializer_; std::unique_ptr<CompositorProtoState> pending_compositor_proto_state_; + ScrollOffsetMap layers_scrolled_; std::unique_ptr<LayerTreeHostInProcessClient> layer_tree_host_in_process_client_;
diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h index af0fad1..8707170f 100644 --- a/cc/test/layer_tree_test.h +++ b/cc/test/layer_tree_test.h
@@ -229,6 +229,10 @@ SINGLE_THREAD_TEST_F(TEST_FIXTURE_NAME); \ MULTI_THREAD_TEST_F(TEST_FIXTURE_NAME) +#define REMOTE_AND_MULTI_THREAD_TEST_F(TEST_FIXTURE_NAME) \ + MULTI_THREAD_TEST_F(TEST_FIXTURE_NAME); \ + REMOTE_TEST_F(TEST_FIXTURE_NAME) + #define SINGLE_MULTI_AND_REMOTE_TEST_F(TEST_FIXTURE_NAME) \ SINGLE_AND_MULTI_THREAD_TEST_F(TEST_FIXTURE_NAME); \ REMOTE_TEST_F(TEST_FIXTURE_NAME)
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc index 31989bb4..ad13182 100644 --- a/cc/trees/draw_property_utils.cc +++ b/cc/trees/draw_property_utils.cc
@@ -241,8 +241,7 @@ // If target is not direct ancestor of clip, this will find least common // ancestor between the target and the clip. - while (target_node->id != EffectTree::kInvalidNodeId && - clip_node->id != ClipTree::kInvalidNodeId) { + while (true) { while (target_node->clip_id > clip_node->id || target_node->has_unclipped_descendants) { target_node = effect_tree.Node(target_node->target_id); @@ -321,11 +320,9 @@ return accumulated_clip_rect; } -template <typename LayerType> -void CalculateClipRects( - const typename LayerType::LayerListType& visible_layer_list, - const PropertyTrees* property_trees, - bool non_root_surfaces_enabled) { +void CalculateClipRects(const std::vector<LayerImpl*>& visible_layer_list, + const PropertyTrees* property_trees, + bool non_root_surfaces_enabled) { const ClipTree& clip_tree = property_trees->clip_tree; for (auto& layer : visible_layer_list) { const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index()); @@ -1119,8 +1116,8 @@ FindLayersThatNeedUpdates(root_layer->layer_tree_impl(), property_trees->transform_tree, property_trees->effect_tree, visible_layer_list); - CalculateClipRects<LayerImpl>(*visible_layer_list, property_trees, - can_render_to_separate_surface); + CalculateClipRects(*visible_layer_list, property_trees, + can_render_to_separate_surface); CalculateVisibleRects(*visible_layer_list, property_trees, can_render_to_separate_surface); } @@ -1271,33 +1268,18 @@ gfx::Transform DrawTransform(const LayerImpl* layer, const TransformTree& transform_tree, const EffectTree& effect_tree) { - gfx::Transform xform; - const bool owns_non_root_surface = - !IsRootLayer(layer) && layer->render_surface(); - if (!owns_non_root_surface) { - // If you're not the root, or you don't own a surface, you need to apply - // your local offset. - xform = - transform_tree.property_trees()->non_root_surfaces_enabled - ? transform_tree.ToTarget(layer->transform_tree_index(), - layer->render_target_effect_tree_index()) - : transform_tree.ToScreen(layer->transform_tree_index()); - if (layer->should_flatten_transform_from_property_tree()) - xform.FlattenTo2d(); - xform.Translate(layer->offset_to_transform_parent().x(), - layer->offset_to_transform_parent().y()); - } else { - // Surfaces need to apply their surface contents scale. - const EffectNode* effect_node = - effect_tree.Node(layer->effect_tree_index()); - xform.Scale(effect_node->surface_contents_scale.x(), - effect_node->surface_contents_scale.y()); -#if DCHECK_IS_ON() - VerifySurfaceContentsScalesMatch(layer->effect_tree_index(), - layer->transform_tree_index(), effect_tree, - transform_tree); -#endif - } + // TransformTree::ToTarget computes transform between the layer's transform + // node and surface's transform node and scales it by the surface's content + // scale. + gfx::Transform xform = + transform_tree.property_trees()->non_root_surfaces_enabled + ? transform_tree.ToTarget(layer->transform_tree_index(), + layer->render_target_effect_tree_index()) + : transform_tree.ToScreen(layer->transform_tree_index()); + if (layer->should_flatten_transform_from_property_tree()) + xform.FlattenTo2d(); + xform.Translate(layer->offset_to_transform_parent().x(), + layer->offset_to_transform_parent().y()); return xform; }
diff --git a/cc/trees/draw_property_utils.h b/cc/trees/draw_property_utils.h index 329d25c..55cbba7 100644 --- a/cc/trees/draw_property_utils.h +++ b/cc/trees/draw_property_utils.h
@@ -36,8 +36,7 @@ gfx::Transform* transform); // Computes combined clips for every node in |clip_tree|. This function requires // that |transform_tree| has been updated via |ComputeTransforms|. -void CC_EXPORT ComputeClips(ClipTree* clip_tree, - const TransformTree& transform_tree, +void CC_EXPORT ComputeClips(PropertyTrees* property_trees, bool non_root_surfaces_enabled); // Computes combined (screen space) transforms for every node in the transform @@ -70,11 +69,6 @@ const EffectTree& effect_tree, LayerList* update_layer_list); -void CC_EXPORT -ComputeVisibleRectsForTesting(PropertyTrees* property_trees, - bool can_render_to_separate_surface, - LayerList* visible_layer_list); - void CC_EXPORT ComputeVisibleRects(LayerImpl* root_layer, PropertyTrees* property_trees, bool can_render_to_separate_surface,
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc index e68e065..a743c677 100644 --- a/cc/trees/layer_tree_host_unittest_scroll.cc +++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -155,7 +155,7 @@ int outer_viewport_container_layer_id_; }; -MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollSimple); +REMOTE_AND_MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollSimple); class LayerTreeHostScrollTestScrollMultipleRedraw : public LayerTreeHostScrollTest {
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index c5b485f68..4304913 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -200,6 +200,9 @@ "/DELAYLOAD:ole32.dll", "/DELAYLOAD:oleaut32.dll", ] + + # Turn on CFG for this project. + configs += [ "//build/config/win:win_msvc_cfg" ] } else if (use_aura) { # Non-Windows aura entrypoint. sources += [ "app/chrome_exe_main_aura.cc" ]
diff --git a/chrome/android/java/res/layout/bottom_toolbar_phone.xml b/chrome/android/java/res/layout/bottom_toolbar_phone.xml new file mode 100644 index 0000000..00d1b0b --- /dev/null +++ b/chrome/android/java/res/layout/bottom_toolbar_phone.xml
@@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2016 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<!-- The toolbar containing the URL bar, back button, and NTP button. +--> + +<org.chromium.chrome.browser.toolbar.BottomToolbarPhone + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/toolbar" + android:layout_width="match_parent" + android:layout_height="@dimen/toolbar_height_no_shadow" > + + <include layout="@layout/toolbar_phone_common"/> + +</org.chromium.chrome.browser.toolbar.BottomToolbarPhone>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java index da94f43..a77232bd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -356,15 +356,19 @@ // of our control, so we have to disable StrictMode to work. See crbug.com/639352. StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); try { - ControlContainer controlContainer = null; setContentView(R.layout.main); if (controlContainerLayoutId != NO_CONTROL_CONTAINER) { ViewStub toolbarContainerStub = ((ViewStub) findViewById(R.id.control_container_stub)); toolbarContainerStub.setLayoutResource(controlContainerLayoutId); - controlContainer = (ControlContainer) toolbarContainerStub.inflate(); + toolbarContainerStub.inflate(); } + // It cannot be assumed that the result of toolbarContainerStub.inflate() will be + // the control container since it may be wrapped in another view. + ControlContainer controlContainer = + (ControlContainer) findViewById(R.id.control_container); + // Inflate the correct toolbar layout for the device. int toolbarLayoutId = getToolbarLayoutId(); if (toolbarLayoutId != NO_TOOLBAR_LAYOUT && controlContainer != null) { @@ -1362,8 +1366,8 @@ * @return A {@link ChromeFullscreenManager} instance that's been created. */ protected ChromeFullscreenManager createFullscreenManager(ControlContainer controlContainer) { - return new ChromeFullscreenManager(this, controlContainer, getTabModelSelector(), - getControlContainerHeightResource(), true); + return new ChromeFullscreenManager( + this, controlContainer, getControlContainerHeightResource(), true); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index b288ecbe..bfd2b1f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -551,8 +551,9 @@ // Bootstrap the first tab as it may have been created before initializing the // fullscreen manager. - if (mTabModelSelectorImpl != null && mTabModelSelectorImpl.getCurrentTab() != null) { - mTabModelSelectorImpl.getCurrentTab().setFullscreenManager(getFullscreenManager()); + if (mTabModelSelectorImpl != null && mTabModelSelectorImpl.getCurrentTab() != null + && getFullscreenManager() != null) { + getFullscreenManager().setTab(mTabModelSelectorImpl.getCurrentTab()); } mFindToolbarManager = new FindToolbarManager(this, @@ -947,8 +948,7 @@ protected int getToolbarLayoutId() { if (DeviceFormFactor.isTablet(getApplicationContext())) return R.layout.toolbar_tablet; - // TODO(mdjones): Replace with bottom_toolbar layout when available. - if (FeatureUtilities.isChromeHomeEnabled()) return R.layout.toolbar_phone; + if (FeatureUtilities.isChromeHomeEnabled()) return R.layout.bottom_toolbar_phone; return R.layout.toolbar_phone; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java index f1609df..8dc2a08 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java
@@ -48,6 +48,7 @@ import org.chromium.chrome.browser.share.ShareHelper; import org.chromium.chrome.browser.webapps.ChromeWebApkHost; import org.chromium.chrome.browser.webapps.WebApkVersionManager; +import org.chromium.chrome.browser.webapps.WebappRegistry; import org.chromium.content.browser.ChildProcessLauncher; import java.util.ArrayList; @@ -173,6 +174,10 @@ mDeferredTasks.add(new Runnable() { @Override public void run() { + // Initialize the WebappRegistry if it's not already initialized. Must be done on + // the main thread. + WebappRegistry.getInstance(); + // Punt all tasks that may block on disk off onto a background thread. initAsyncDiskTask(); @@ -276,11 +281,21 @@ SystemClock.uptimeMillis() - asyncTaskStartTime, TimeUnit.MILLISECONDS); + // Warm up all web app shared prefs. This must be run after the WebappRegistry + // instance is initialized. + WebappRegistry.warmUpSharedPrefs(); + return null; } finally { TraceEvent.end("ChromeBrowserInitializer.onDeferredStartup.doInBackground"); } } + + @Override + protected void onPostExecute(Void params) { + // Must be run on the UI thread after the WebappRegistry has been completely warmed. + WebappRegistry.getInstance().unregisterOldWebapps(System.currentTimeMillis()); + } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java b/chrome/android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java index a7ed074..2924c65 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java
@@ -16,7 +16,6 @@ import org.chromium.chrome.browser.tabmodel.document.TabDelegate; import org.chromium.chrome.browser.webapps.WebappDataStorage; import org.chromium.chrome.browser.webapps.WebappRegistry; -import org.chromium.chrome.browser.webapps.WebappRegistry.FetchWebappDataStorageCallback; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.common.Referrer; @@ -74,49 +73,46 @@ // 2. Launch WebappActivity if one matches the target URL and was opened recently. // Otherwise, open the URL in a tab. - FetchWebappDataStorageCallback callback = new FetchWebappDataStorageCallback() { - @Override - public void onWebappDataStorageRetrieved(final WebappDataStorage storage) { - // If we do not find a WebappDataStorage corresponding to this URL, or if it hasn't - // been opened recently enough, open the URL in a tab. - if (storage == null || !storage.wasLaunchedRecently()) { - LoadUrlParams loadUrlParams = new LoadUrlParams(url, PageTransition.LINK); - loadUrlParams.setPostData(postData); - loadUrlParams.setVerbatimHeaders(extraHeaders); - loadUrlParams.setReferrer(new Referrer(referrerUrl, referrerPolicy)); + final WebappDataStorage storage = + WebappRegistry.getInstance().getWebappDataStorageForUrl(url); - AsyncTabCreationParams asyncParams = new AsyncTabCreationParams(loadUrlParams, - requestId); - tabDelegate.createNewTab(asyncParams, TabLaunchType.FROM_CHROME_UI, - Tab.INVALID_TAB_ID); - } else { - // The URL is within the scope of a recently launched standalone-capable web app - // on the home screen, so open it a standalone web app frame. An AsyncTask is - // used because WebappDataStorage.createWebappLaunchIntent contains a Bitmap - // decode operation and should not be run on the UI thread. - // - // This currently assumes that the only source is notifications; any future use - // which adds a different source will need to change this. - new AsyncTask<Void, Void, Intent>() { - @Override - protected final Intent doInBackground(Void... nothing) { - return storage.createWebappLaunchIntent(); - } + // If we do not find a WebappDataStorage corresponding to this URL, or if it hasn't + // been opened recently enough, open the URL in a tab. + if (storage == null || !storage.wasLaunchedRecently()) { + LoadUrlParams loadUrlParams = new LoadUrlParams(url, PageTransition.LINK); + loadUrlParams.setPostData(postData); + loadUrlParams.setVerbatimHeaders(extraHeaders); + loadUrlParams.setReferrer(new Referrer(referrerUrl, referrerPolicy)); - @Override - protected final void onPostExecute(Intent intent) { - // Replace the web app URL with the URL from the notification. This is - // within the webapp's scope, so it is valid. - intent.putExtra(ShortcutHelper.EXTRA_URL, url); - intent.putExtra(ShortcutHelper.EXTRA_SOURCE, - ShortcutSource.NOTIFICATION); - tabDelegate.createNewStandaloneFrame(intent); - } - }.execute(); + AsyncTabCreationParams asyncParams = new AsyncTabCreationParams(loadUrlParams, + requestId); + tabDelegate.createNewTab(asyncParams, TabLaunchType.FROM_CHROME_UI, + Tab.INVALID_TAB_ID); + } else { + // The URL is within the scope of a recently launched standalone-capable web app + // on the home screen, so open it a standalone web app frame. An AsyncTask is + // used because WebappDataStorage.createWebappLaunchIntent contains a Bitmap + // decode operation and should not be run on the UI thread. + // + // This currently assumes that the only source is notifications; any future use + // which adds a different source will need to change this. + new AsyncTask<Void, Void, Intent>() { + @Override + protected final Intent doInBackground(Void... nothing) { + return storage.createWebappLaunchIntent(); } - } - }; - WebappRegistry.getWebappDataStorageForUrl(url, callback); + + @Override + protected final void onPostExecute(Intent intent) { + // Replace the web app URL with the URL from the notification. This is + // within the webapp's scope, so it is valid. + intent.putExtra(ShortcutHelper.EXTRA_URL, url); + intent.putExtra(ShortcutHelper.EXTRA_SOURCE, + ShortcutSource.NOTIFICATION); + tabDelegate.createNewStandaloneFrame(intent); + } + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java index 996c76b79..04cc8ff 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
@@ -168,7 +168,7 @@ // Store the webapp data so that it is accessible without the intent. Once this // process is complete, call back to native code to start the splash image // download. - WebappRegistry.registerWebapp( + WebappRegistry.getInstance().register( id, new WebappRegistry.FetchWebappDataStorageCallback() { @Override public void onWebappDataStorageRetrieved(WebappDataStorage storage) { @@ -228,7 +228,7 @@ } /** - * Creates a storage location and stores the data for a web app using {@link WebappDataStorage}. + * Stores the specified bitmap as the splash screen for a web app. * @param id ID of the web app which is storing data. * @param splashImage Image which should be displayed on the splash screen of * the web app. This can be null of there is no image to show. @@ -236,16 +236,20 @@ @SuppressWarnings("unused") @CalledByNative private static void storeWebappSplashImage(final String id, final Bitmap splashImage) { - WebappRegistry.getWebappDataStorage( - id, new WebappRegistry.FetchWebappDataStorageCallback() { - @Override - public void onWebappDataStorageRetrieved(WebappDataStorage storage) { - if (storage == null) return; + final WebappDataStorage storage = WebappRegistry.getInstance().getWebappDataStorage(id); + if (storage != null) { + new AsyncTask<Void, Void, String>() { + @Override + protected String doInBackground(Void... args0) { + return encodeBitmapAsString(splashImage); + } - storage.updateSplashScreenImage(splashImage); - } - - }); + @Override + protected void onPostExecute(String encodedImage) { + storage.updateSplashScreenImage(encodedImage); + } + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java index e9e8d15..4f11f59 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -364,7 +364,7 @@ } }); - mMainTab.setFullscreenManager(getFullscreenManager()); + getFullscreenManager().setTab(mMainTab); mCustomTabContentHandler = new CustomTabContentHandler() { @Override public void loadUrlAndTrackFromTimestamp(LoadUrlParams params, long timestamp) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicy.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicy.java index f3ea43ad..f54e4b12 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicy.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicy.java
@@ -191,6 +191,10 @@ } @Override + public void notifyStateLoaded(int tabCountAtStartup) { + } + + @Override public void destroy() { mDestroyed = true; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/FilterAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/FilterAdapter.java index 82f3a514..06924a2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/FilterAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/FilterAdapter.java
@@ -69,6 +69,8 @@ labelView.setBackground(null); iconDrawable = TintedDrawable.constructTintedDrawable( resources, iconId, R.color.descriptive_text_color); + labelView.setTextColor( + ApiCompatibilityUtils.getColor(resources, R.color.default_text_color)); } labelView.setCompoundDrawablesWithIntrinsicBounds(iconDrawable, null, null, null);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalauth/ExternalAuthUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/externalauth/ExternalAuthUtils.java index c306ad8..d986610 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/externalauth/ExternalAuthUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/externalauth/ExternalAuthUtils.java
@@ -166,6 +166,21 @@ } /** + * @return Whether the current device lacks proper Google Play Services. This will return true + * if the service is not authentic or it is totally missing. Return false otherwise. + * Note this method returns false if the service is only temporarily disabled, such as + * when it is updating. + */ + public boolean isGooglePlayServicesMissing(final Context context) { + final int resultCode = checkGooglePlayServicesAvailable(context); + if (resultCode == ConnectionResult.SERVICE_MISSING + || resultCode == ConnectionResult.SERVICE_INVALID) { + return true; + } + return false; + } + + /** * Checks whether Google Play Services can be used, applying the specified error-handling * policy if a user-recoverable error occurs. This method is threadsafe. If the specified * error-handling policy requires UI interaction, it will be run on the UI thread.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java index 9089173d..894fe33 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
@@ -88,8 +88,9 @@ @VisibleForTesting protected boolean isSyncAllowed() { - return FeatureUtilities.canAllowSync(mActivity) - && !SigninManager.get(mActivity.getApplicationContext()).isSigninDisabledByPolicy(); + SigninManager signinManager = SigninManager.get(mActivity.getApplicationContext()); + return FeatureUtilities.canAllowSync(mActivity) && !signinManager.isSigninDisabledByPolicy() + && signinManager.isSigninSupported(); } @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java index 15b30a6e..eb14180 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java
@@ -31,7 +31,6 @@ import org.chromium.base.VisibleForTesting; import org.chromium.chrome.browser.fullscreen.FullscreenHtmlApiHandler.FullscreenHtmlApiDelegate; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.widget.ControlContainer; import org.chromium.content.browser.ContentVideoView; import org.chromium.content.browser.ContentViewCore; @@ -181,15 +180,13 @@ * Creates an instance of the fullscreen mode manager. * @param activity The activity that supports fullscreen. * @param controlContainer Container holding the controls (Toolbar). - * @param modelSelector The model selector providing access to the current tab. * @param resControlContainerHeight The dimension resource ID for the control container height. * @param supportsBrowserOverride Whether we want to disable the token system used by the browser. */ public ChromeFullscreenManager(Activity activity, ControlContainer controlContainer, - TabModelSelector modelSelector, int resControlContainerHeight, - boolean supportsBrowserOverride) { - super(activity.getWindow(), modelSelector); + int resControlContainerHeight, boolean supportsBrowserOverride) { + super(activity.getWindow()); mActivity = activity; ApplicationStatus.registerStateListenerForActivity(this, activity); @@ -240,7 +237,7 @@ return new FullscreenHtmlApiDelegate() { @Override public void onEnterFullscreen() { - Tab tab = getActiveTab(); + Tab tab = getTab(); if (getControlOffset() == -mControlContainerHeight) { // The top controls are currently hidden. getHtmlApiHandler().enterFullscreen(tab); @@ -510,7 +507,7 @@ } } - final Tab tab = getActiveTab(); + final Tab tab = getTab(); if (tab != null && offset == -mControlContainerHeight && mIsEnteringPersistentModeState) { getHtmlApiHandler().enterFullscreen(tab); mIsEnteringPersistentModeState = false; @@ -595,19 +592,14 @@ } } - private Tab getActiveTab() { - Tab tab = getTabModelSelector().getCurrentTab(); - return tab; - } - private ContentViewCore getActiveContentViewCore() { - Tab tab = getActiveTab(); + Tab tab = getTab(); return tab != null ? tab.getContentViewCore() : null; } @Override public void setPositionsForTabToNonFullscreen() { - Tab tab = getActiveTab(); + Tab tab = getTab(); if (tab == null || tab.isShowingTopControlsEnabled()) { setPositionsForTab(0, mControlContainerHeight); } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/FullscreenManager.java b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/FullscreenManager.java index 92b03cb0..feec82b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/FullscreenManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/FullscreenManager.java
@@ -9,7 +9,6 @@ import org.chromium.chrome.browser.fullscreen.FullscreenHtmlApiHandler.FullscreenHtmlApiDelegate; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.tabmodel.TabModelSelector; /** * Manages the basic fullscreen functionality required by a Tab. @@ -19,20 +18,17 @@ public abstract class FullscreenManager { public static final int INVALID_TOKEN = -1; - private final TabModelSelector mModelSelector; private final FullscreenHtmlApiHandler mHtmlApiHandler; private boolean mOverlayVideoMode; + private Tab mTab; /** * Constructs the basic ChromeTab oriented FullscreenManager. * * @param window Top-level window to turn to fullscreen. - * @param modelSelector The model selector providing access to the current tab. */ - public FullscreenManager(Window window, TabModelSelector modelSelector) { - mModelSelector = modelSelector; + public FullscreenManager(Window window) { mHtmlApiHandler = new FullscreenHtmlApiHandler(window, createApiDelegate()); - mOverlayVideoMode = false; } /** @@ -49,13 +45,6 @@ } /** - * @return The selector for accessing the current Tab. - */ - protected TabModelSelector getTabModelSelector() { - return mModelSelector; - } - - /** * Trigger a temporary showing of the top controls. */ public abstract void showControlsTransient(); @@ -132,6 +121,28 @@ public abstract void updateContentViewChildrenState(); /** + * Sets the currently selected tab for fullscreen. + */ + public void setTab(Tab tab) { + if (mTab == tab) return; + + // Remove the fullscreen manager from the old tab before setting the new tab. + if (mTab != null) mTab.setFullscreenManager(null); + + mTab = tab; + + // Initialize the new tab with the correct fullscreen manager reference. + if (mTab != null) mTab.setFullscreenManager(this); + } + + /** + * @return The currently selected tab for fullscreen. + */ + public Tab getTab() { + return mTab; + } + + /** * Enters or exits persistent fullscreen mode. In this mode, the top controls will be * permanently hidden until this mode is exited. * @@ -140,7 +151,7 @@ public void setPersistentFullscreenMode(boolean enabled) { mHtmlApiHandler.setPersistentFullscreenMode(enabled); - Tab tab = mModelSelector.getCurrentTab(); + Tab tab = getTab(); if (tab != null) { tab.updateFullscreenEnabledState(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AppBannerInfoBarDelegateAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AppBannerInfoBarDelegateAndroid.java index eb0ced50..e6763bcb6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AppBannerInfoBarDelegateAndroid.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AppBannerInfoBarDelegateAndroid.java
@@ -155,13 +155,12 @@ } @CalledByNative - private void openWebApk(String packageName) { + private void openWebApk() { Context context = ContextUtils.getApplicationContext(); PackageManager packageManager = getPackageManager(context); - if (InstallerDelegate.isInstalled(packageManager, packageName)) { - mWebApkPackage = null; - openApp(context, packageName); + if (InstallerDelegate.isInstalled(packageManager, mWebApkPackage)) { + openApp(context, mWebApkPackage); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationService.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationService.java index 4b3eed1..176e45f0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationService.java
@@ -8,12 +8,14 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.os.StrictMode; import android.util.Log; import org.chromium.base.ThreadUtils; import org.chromium.base.annotations.SuppressFBWarnings; import org.chromium.base.library_loader.ProcessInitException; import org.chromium.chrome.browser.init.ChromeBrowserInitializer; +import org.chromium.chrome.browser.webapps.WebappRegistry; /** * The Notification service receives intents fired as responses to user actions issued on Android @@ -76,6 +78,18 @@ try { ChromeBrowserInitializer.getInstance(this).handleSynchronousStartup(); + // Warm up the WebappRegistry, as we need to check if this notification should launch a + // standalone web app. This no-ops if the registry is already initialized and warmed, + // but triggers a strict mode violation otherwise (i.e. the browser isn't running). + // Temporarily disable strict mode to work around the violation. + StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); + try { + WebappRegistry.getInstance(); + WebappRegistry.warmUpSharedPrefs(); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } + // Now that the browser process is initialized, we pass forward the call to the // NotificationPlatformBridge which will take care of delivering the appropriate events. if (!NotificationPlatformBridge.dispatchNotificationEvent(intent)) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java index 11a6d97..8f511df 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java
@@ -380,7 +380,7 @@ * @return Whether sync promo should be displayed. */ public boolean shouldDisplaySyncPromo() { - if (SigninManager.get(mContext).isSigninDisabledByPolicy()) { + if (!SigninManager.get(mContext).isSignInAllowed()) { return false; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java index a767a7b..3b635b89 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java
@@ -47,7 +47,8 @@ public SignInPromo() { mDismissed = ChromePreferenceManager.getInstance(ContextUtils.getApplicationContext()) .getNewTabPageSigninPromoDismissed(); - mVisible = !SigninManager.get(ContextUtils.getApplicationContext()).isSignedInOnNative(); + SigninManager signinManager = SigninManager.get(ContextUtils.getApplicationContext()); + mVisible = signinManager.isSignInAllowed() && !signinManager.isSignedInOnNative(); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java index 03165867..c5a8eec 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -674,6 +674,12 @@ } else if (animation == mNavigationIconShowAnimator) { mSecurityButton.setVisibility(INVISIBLE); } + // This is done specifically not to show offline page verbose status with the + // icon. It should be properly solved, when omnibox verbose status animation is + // implemented. See: http://crbug.com/648129 + updateVerboseStatusVisibility(); + // URL cleanup to not show not emphasized URL next to padlock. + setUrlToPageUrl(); } @Override @@ -683,6 +689,8 @@ } else if (animation == mNavigationIconShowAnimator) { mNavigationButton.setVisibility(VISIBLE); } + // As above. See: http://crbug.com/648129 + updateVerboseStatusVisibility(); } }; @@ -1389,8 +1397,10 @@ * omnibox. */ private void updateVerboseStatusVisibility() { - boolean verboseStatusVisible = - mNavigationButtonType == NavigationButtonType.OFFLINE && !mUrlHasFocus; + boolean verboseStatusVisible = !mUrlHasFocus + && mNavigationButtonType == NavigationButtonType.OFFLINE + && mNavigationButton.getVisibility() == VISIBLE + && mSecurityButton.getVisibility() == INVISIBLE; int verboseStatusVisibility = verboseStatusVisible ? VISIBLE : GONE;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java index 318d267..fe60ed16 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java
@@ -11,7 +11,6 @@ import android.preference.Preference; import android.preference.PreferenceFragment; -import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.VisibleForTesting; import org.chromium.blimp_public.BlimpClientContext; import org.chromium.chrome.R; @@ -55,8 +54,6 @@ private SignInPreference mSignInPreference; private ManagedPreferenceDelegate mManagedPreferenceDelegate; - private boolean mIsDemoUser; - public MainPreferences() { setHasOptionsMenu(true); mManagedPreferenceDelegate = createManagedPreferenceDelegate(); @@ -65,8 +62,6 @@ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - - mIsDemoUser = ApiCompatibilityUtils.isDemoUser(getActivity()); } @Override @@ -76,17 +71,16 @@ // the SignInPreference. updatePreferences(); - if (!mIsDemoUser) { + if (SigninManager.get(getActivity()).isSigninSupported()) { SigninManager.get(getActivity()).addSignInStateObserver(this); setupSignInPref(); } - } @Override public void onPause() { super.onPause(); - if (!mIsDemoUser) { + if (SigninManager.get(getActivity()).isSigninSupported()) { SigninManager.get(getActivity()).removeSignInStateObserver(this); clearSignInPref(); } @@ -169,7 +163,7 @@ getPreferenceScreen().removePreference(dataReduction); } - if (mIsDemoUser) { + if (!SigninManager.get(getActivity()).isSigninSupported()) { getPreferenceScreen().removePreference(findPreference(PREF_SIGN_IN)); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java index 77bbbb5..2e58c4f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
@@ -235,9 +235,9 @@ * Returns true if signin can be started now. */ public boolean isSignInAllowed() { - return mSigninAllowedByPolicy && !mFirstRunCheckIsPending && mSignInState == null + return !mFirstRunCheckIsPending && mSignInState == null && mSigninAllowedByPolicy && ChromeSigninController.get(mContext).getSignedInUser() == null - && !ApiCompatibilityUtils.isDemoUser(mContext); + && isSigninSupported(); } /** @@ -248,6 +248,15 @@ } /** + * @return Whether true if the current user is not demo user and the user has a reasonable + * Google Play Services installed. + */ + public boolean isSigninSupported() { + return !ApiCompatibilityUtils.isDemoUser(mContext) + && !ExternalAuthUtils.getInstance().isGooglePlayServicesMissing(mContext); + } + + /** * Registers a SignInStateObserver to be notified when the user signs in or out of Chrome. */ public void addSignInStateObserver(SignInStateObserver observer) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java index 4284d134..3c696d5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java
@@ -7,10 +7,10 @@ import android.os.Handler; import org.chromium.base.VisibleForTesting; -import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior; import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; +import org.chromium.chrome.browser.fullscreen.FullscreenManager; import org.chromium.chrome.browser.ntp.NativePageFactory; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; @@ -69,24 +69,6 @@ public void onStateLoaded() { markTabStateInitialized(); } - - @Override - public void onStateMerged() { - } - - @Override - public void onDetailsRead(int index, int id, String url, boolean isStandardActiveIndex, - boolean isIncognitoActiveIndex) { - } - - @Override - public void onInitialized(int tabCountAtStartup) { - RecordHistogram.recordCountHistogram("Tabs.CountAtStartup", tabCountAtStartup); - } - - @Override - public void onMetadataSavedAsynchronously() { - } }; mIsUndoSupported = supportUndo; mTabSaver = new TabPersistentStore( @@ -348,6 +330,7 @@ if (mVisibleTab != tab && tab != null && !tab.isNativePage()) { TabModelImpl.startTabSwitchLatencyTiming(type); } + FullscreenManager fullscreenManager = mActivity.getFullscreenManager(); if (mVisibleTab != null && mVisibleTab != tab && !mVisibleTab.needsReload()) { if (mVisibleTab.isInitialized() && !mVisibleTab.isDetachedForReparenting()) { // TODO(dtrainor): Once we figure out why we can't grab a snapshot from the current @@ -358,7 +341,7 @@ cacheTabBitmap(mVisibleTab); } mVisibleTab.hide(); - mVisibleTab.setFullscreenManager(null); + if (fullscreenManager != null) fullscreenManager.setTab(null); mTabSaver.addTabToSaveQueue(mVisibleTab); } mVisibleTab = null; @@ -377,7 +360,7 @@ return; } - tab.setFullscreenManager(mActivity.getFullscreenManager()); + if (fullscreenManager != null) fullscreenManager.setTab(tab); mVisibleTab = tab; // Don't execute the tab display part if Chrome has just been sent to background. This
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistencePolicy.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistencePolicy.java index 5ba88a45..d3f92c63 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistencePolicy.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistencePolicy.java
@@ -97,6 +97,12 @@ void setTabContentManager(TabContentManager cache); /** + * Notified when {@link TabPersistentStore#loadState(boolean)} has completed. + * @param tabCountAtStartup The number of tabs to be restored at startup. + */ + void notifyStateLoaded(int tabCountAtStartup); + + /** * Notify that persistent store has been destroyed. */ void destroy();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java index 12c23366..9f95debf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
@@ -102,35 +102,35 @@ /** * Alerted at various stages of operation. */ - public static interface TabPersistentStoreObserver { + public abstract static class TabPersistentStoreObserver { /** * To be called when the file containing the initial information about the TabModels has * been loaded. * @param tabCountAtStartup How many tabs there are in the TabModels. */ - void onInitialized(int tabCountAtStartup); + void onInitialized(int tabCountAtStartup) {} /** * Called when details about a Tab are read from the metadata file. */ void onDetailsRead(int index, int id, String url, - boolean isStandardActiveIndex, boolean isIncognitoActiveIndex); + boolean isStandardActiveIndex, boolean isIncognitoActiveIndex) {} /** * To be called when the TabStates have all been loaded. */ - void onStateLoaded(); + void onStateLoaded() {} /** * To be called when the TabState from another instance has been merged. */ - void onStateMerged(); + void onStateMerged() {} /** * Called when the metadata file has been saved out asynchronously. * This currently does not get called when the metadata file is saved out on the UI thread. */ - void onMetadataSavedAsynchronously(); + void onMetadataSavedAsynchronously() {} } /** Stores information about a TabModel. */ @@ -399,6 +399,7 @@ Log.d(TAG, "loadState exception: " + e.toString(), e); } + mPersistencePolicy.notifyStateLoaded(mTabsToRestore.size()); if (mObserver != null) mObserver.onInitialized(mTabsToRestore.size()); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabbedModeTabPersistencePolicy.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabbedModeTabPersistencePolicy.java index 25bb10b9..5688aca 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabbedModeTabPersistencePolicy.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabbedModeTabPersistencePolicy.java
@@ -360,6 +360,11 @@ } @Override + public void notifyStateLoaded(int tabCountAtStartup) { + RecordHistogram.recordCountHistogram("Tabs.CountAtStartup", tabCountAtStartup); + } + + @Override public void destroy() { mDestroyed = true; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarPhone.java new file mode 100644 index 0000000..af5e6db --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarPhone.java
@@ -0,0 +1,31 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.toolbar; + +import android.content.Context; +import android.util.AttributeSet; + +import org.chromium.chrome.R; + +/** + * Phone specific toolbar that exists at the bottom of the screen. + */ +public class BottomToolbarPhone extends ToolbarPhone { + /** + * Constructs a BottomToolbarPhone object. + * @param context The Context in which this View object is created. + * @param attrs The AttributeSet that was specified with this View. + */ + public BottomToolbarPhone(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected int getProgressBarTopMargin() { + // In the case where the toolbar is at the bottom of the screen, the progress bar should + // be at the top of the toolbar. + return getContext().getResources().getDimensionPixelSize(R.dimen.toolbar_shadow_height); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java index e2c96c0..28e7d3c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
@@ -96,6 +96,15 @@ ApiCompatibilityUtils.getColorStateList(getResources(), R.color.light_mode_tint); } + /** + * Get the top margin of the progress bar relative to the toolbar layout. This is used to set + * the position of the progress bar (either top or bottom of the toolbar). + * @return The top margin of the progress bar. + */ + protected int getProgressBarTopMargin() { + return mToolbarHeightWithoutShadow - mProgressBar.getLayoutParams().height; + } + @Override protected void onFinishInflate() { super.onFinishInflate(); @@ -103,7 +112,7 @@ mProgressBar = (ToolbarProgressBar) findViewById(R.id.progress); if (mProgressBar != null) { removeView(mProgressBar); - mProgressBar.prepareForAttach(mToolbarHeightWithoutShadow); + mProgressBar.prepareForAttach(getProgressBarTopMargin()); if (isNativeLibraryReady()) mProgressBar.initializeAnimation(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/FullScreenActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/FullScreenActivity.java index 4ee99e9a..4bb4c35 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/FullScreenActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/FullScreenActivity.java
@@ -81,7 +81,7 @@ (View) controlContainer, (ViewGroup) findViewById(android.R.id.content), controlContainer); - getActivityTab().setFullscreenManager(getFullscreenManager()); + if (getFullscreenManager() != null) getFullscreenManager().setTab(getActivityTab()); super.finishNativeInitialization(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/ManifestUpgradeDetector.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/ManifestUpgradeDetector.java index c95dcba..3020fae9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/ManifestUpgradeDetector.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/ManifestUpgradeDetector.java
@@ -69,24 +69,6 @@ private Callback mCallback; /** - * Gets the Murmur2 hash from a Bundle. Returns an empty string if the value could not be - * parsed. - */ - private static String getMurmur2HashFromBundle(Bundle bundle) { - String value = bundle.getString(WebApkMetaDataKeys.ICON_MURMUR2_HASH); - - // The Murmur2 hash should be terminated with 'L' to force the value to be a string. - // According to https://developer.android.com/guide/topics/manifest/meta-data-element.html - // numeric <meta-data> values can only be retrieved via {@link Bundle#getInt()} and - // {@link Bundle#getFloat()}. We cannot use {@link Bundle#getFloat()} due to loss of - // precision. - if (value == null || !value.endsWith("L")) { - return ""; - } - return value.substring(0, value.length() - 1); - } - - /** * Creates an instance of {@link ManifestUpgradeDetector}. * * @param tab WebAPK's tab. @@ -137,7 +119,8 @@ mManifestUrl = IntentUtils.safeGetString(metadata, WebApkMetaDataKeys.WEB_MANIFEST_URL); mStartUrl = IntentUtils.safeGetString(metadata, WebApkMetaDataKeys.START_URL); mIconUrl = IntentUtils.safeGetString(metadata, WebApkMetaDataKeys.ICON_URL); - mIconMurmur2Hash = getMurmur2HashFromBundle(metadata); + mIconMurmur2Hash = Long.toString(WebApkMetaDataUtils.getLongFromMetaData( + metadata, WebApkMetaDataKeys.ICON_MURMUR2_HASH, 0)); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java index 8c03ea5..d3cd116 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
@@ -51,7 +51,7 @@ // Register the WebAPK. It is possible that a WebAPK's meta data was deleted when user // cleared Chrome's data. When it is launched again, we know that the WebAPK is still // installed, so re-register it. - WebappRegistry.registerWebapp( + WebappRegistry.getInstance().register( mWebappInfo.id(), new WebappRegistry.FetchWebappDataStorageCallback() { @Override public void onWebappDataStorageRetrieved(WebappDataStorage storage) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkMetaDataUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkMetaDataUtils.java new file mode 100644 index 0000000..ef655be --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkMetaDataUtils.java
@@ -0,0 +1,152 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.webapps; + +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.text.TextUtils; + +import org.chromium.base.ContextUtils; +import org.chromium.blink_public.platform.WebDisplayMode; +import org.chromium.chrome.browser.ShortcutHelper; +import org.chromium.chrome.browser.util.IntentUtils; +import org.chromium.content_public.common.ScreenOrientationValues; +import org.chromium.webapk.lib.common.WebApkConstants; +import org.chromium.webapk.lib.common.WebApkMetaDataKeys; + +/** + * Contains methods for extracting meta data from WebAPK. + */ +public class WebApkMetaDataUtils { + /** + * Populates {@link WebappInfo} with meta data extracted from WebAPK. + * @param webApkPackageName Package name of the WebAPK to extract meta data from. + * @param url WebAPK start URL. + * @param source {@link ShortcutSource} that the WebAPK was opened from. + */ + public static WebappInfo extractWebappInfoFromWebApk( + String webApkPackageName, String url, int source) { + PackageManager packageManager = ContextUtils.getApplicationContext().getPackageManager(); + ApplicationInfo appInfo; + try { + appInfo = packageManager.getApplicationInfo( + webApkPackageName, PackageManager.GET_META_DATA); + } catch (PackageManager.NameNotFoundException e) { + return null; + } + Bundle metaData = appInfo.metaData; + String scope = IntentUtils.safeGetString(metaData, WebApkMetaDataKeys.SCOPE); + String name = IntentUtils.safeGetString(metaData, WebApkMetaDataKeys.NAME); + String shortName = IntentUtils.safeGetString(metaData, WebApkMetaDataKeys.SHORT_NAME); + int displayMode = displayModeFromString( + IntentUtils.safeGetString(metaData, WebApkMetaDataKeys.DISPLAY_MODE)); + int orientation = orientationFromString( + IntentUtils.safeGetString(metaData, WebApkMetaDataKeys.ORIENTATION)); + long themeColor = getLongFromMetaData(metaData, WebApkMetaDataKeys.THEME_COLOR, + ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING); + long backgroundColor = getLongFromMetaData(metaData, WebApkMetaDataKeys.BACKGROUND_COLOR, + ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING); + boolean isIconGenerated = + TextUtils.isEmpty(IntentUtils.safeGetString(metaData, WebApkMetaDataKeys.ICON_URL)); + + int iconId = IntentUtils.safeGetInt(metaData, WebApkMetaDataKeys.ICON_ID, 0); + Resources resources; + try { + resources = packageManager.getResourcesForApplication(webApkPackageName); + } catch (PackageManager.NameNotFoundException e) { + return null; + } + Bitmap icon = BitmapFactory.decodeResource(resources, iconId); + String encodedIcon = ShortcutHelper.encodeBitmapAsString(icon); + + return WebappInfo.create(WebApkConstants.WEBAPK_ID_PREFIX + webApkPackageName, url, scope, + encodedIcon, name, shortName, displayMode, orientation, source, themeColor, + backgroundColor, isIconGenerated, webApkPackageName); + } + + /** + * Extracts long value from the WebAPK's meta data. + * @param metaData WebAPK meta data to extract the long from. + * @param name Name of the <meta-data> tag to extract the value from. + * @param defaultValue Value to return if long value could not be extracted. + * @return long value. + */ + public static long getLongFromMetaData(Bundle metaData, String name, long defaultValue) { + String value = metaData.getString(name); + + // The value should be terminated with 'L' to force the value to be a string. According to + // https://developer.android.com/guide/topics/manifest/meta-data-element.html numeric + // meta data values can only be retrieved via {@link Bundle#getInt()} and + // {@link Bundle#getFloat()}. We cannot use {@link Bundle#getFloat()} due to loss of + // precision. + if (value == null || !value.endsWith("L")) { + return defaultValue; + } + try { + return Long.parseLong(value.substring(0, value.length() - 1)); + } catch (NumberFormatException e) { + } + return defaultValue; + } + + /** + * Returns the WebDisplayMode which matches {@link displayMode}. + * @param displayMode One of https://www.w3.org/TR/appmanifest/#dfn-display-modes-values + * @return The matching WebDisplayMode. {@link WebDisplayMode#Undefined} if there is no match. + */ + private static int displayModeFromString(String displayMode) { + if (displayMode == null) { + return WebDisplayMode.Undefined; + } + + if (displayMode.equals("fullscreen")) { + return WebDisplayMode.Fullscreen; + } else if (displayMode.equals("standalone")) { + return WebDisplayMode.Standalone; + } else if (displayMode.equals("minimal-ui")) { + return WebDisplayMode.MinimalUi; + } else if (displayMode.equals("browser")) { + return WebDisplayMode.Browser; + } else { + return WebDisplayMode.Undefined; + } + } + + /** + * Returns the ScreenOrientationValue which matches {@link orientation}. + * @param orientation One of https://w3c.github.io/screen-orientation/#orientationlocktype-enum + * @return The matching ScreenOrientationValue. {@link ScreenOrientationValues#DEFAULT} if there + * is no match. + */ + private static int orientationFromString(String orientation) { + if (orientation == null) { + return ScreenOrientationValues.DEFAULT; + } + + if (orientation.equals("any")) { + return ScreenOrientationValues.ANY; + } else if (orientation.equals("natural")) { + return ScreenOrientationValues.NATURAL; + } else if (orientation.equals("landscape")) { + return ScreenOrientationValues.LANDSCAPE; + } else if (orientation.equals("landscape-primary")) { + return ScreenOrientationValues.LANDSCAPE_PRIMARY; + } else if (orientation.equals("landscape-secondary")) { + return ScreenOrientationValues.LANDSCAPE_SECONDARY; + } else if (orientation.equals("portrait")) { + return ScreenOrientationValues.PORTRAIT; + } else if (orientation.equals("portrait-primary")) { + return ScreenOrientationValues.PORTRAIT_PRIMARY; + } else if (orientation.equals("portrait-secondary")) { + return ScreenOrientationValues.PORTRAIT_SECONDARY; + } else { + return ScreenOrientationValues.DEFAULT; + } + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java index f9ec21c..6f15044d7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java
@@ -16,7 +16,6 @@ import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.util.IntentUtils; -import org.chromium.chrome.browser.webapps.WebappRegistry.FetchWebappDataStorageCallback; import org.chromium.webapk.lib.client.WebApkVersion; import org.chromium.webapk.lib.common.WebApkMetaDataKeys; @@ -77,32 +76,22 @@ mUpgradeDetector = new ManifestUpgradeDetector(tab, info, metadata, this); - WebappRegistry.FetchWebappDataStorageCallback callback = - new WebappRegistry.FetchWebappDataStorageCallback() { - @Override - public void onWebappDataStorageRetrieved(WebappDataStorage storage) { - if (forceUpgrade(storage)) { - mForceUpgrade = true; - } + WebappDataStorage storage = WebappRegistry.getInstance().getWebappDataStorage(info.id()); + if (forceUpgrade(storage)) mForceUpgrade = true; - // TODO(pkotwicz|hanxi): Request upgrade if ShellAPK version changes if - // ManifestUpgradeDetector cannot fetch the Web Manifest. For instance, the - // web developer may have removed the Web Manifest from their site. - // (http://crbug.com/639536) + // TODO(pkotwicz|hanxi): Request upgrade if ShellAPK version changes if + // ManifestUpgradeDetector cannot fetch the Web Manifest. For instance, the web developer + // may have removed the Web Manifest from their site. (http://crbug.com/639536) - long sinceLastCheckDuration = System.currentTimeMillis() - - storage.getLastCheckForWebManifestUpdateTime(); - if (sinceLastCheckDuration > FULL_CHECK_UPDATE_INTERVAL || mForceUpgrade) { - if (mUpgradeDetector.start()) { - // crbug.com/636525. The timestamp of the last check for updated - // Web Manifest should be updated after the detector finds the - // Web Manifest, not when the detector is started. - storage.updateTimeOfLastCheckForUpdatedWebManifest(); - } - } - } - }; - WebappRegistry.getWebappDataStorage(info.id(), callback); + long sinceLastCheckDuration = System.currentTimeMillis() + - storage.getLastCheckForWebManifestUpdateTime(); + if (sinceLastCheckDuration > FULL_CHECK_UPDATE_INTERVAL || mForceUpgrade) { + if (mUpgradeDetector.start()) { + // crbug.com/636525. The timestamp of the last manifest update check should be + // updated after the detector finds the manifest, not when the detector is started. + storage.updateTimeOfLastCheckForUpdatedWebManifest(); + } + } } @Override @@ -177,16 +166,11 @@ */ @CalledByNative private static void onBuiltWebApk(String id, final boolean success) { - WebappRegistry.getWebappDataStorage(id, - new FetchWebappDataStorageCallback() { - @Override - public void onWebappDataStorageRetrieved(WebappDataStorage storage) { - // Update the request time and result together. It prevents getting a - // correct request time but a result from the previous request. - storage.updateTimeOfLastWebApkUpdateRequestCompletion(); - storage.updateDidLastWebApkUpdateRequestSucceed(success); - } - }); + WebappDataStorage storage = WebappRegistry.getInstance().getWebappDataStorage(id); + // Update the request time and result together. It prevents getting a correct request time + // but a result from the previous request. + storage.updateTimeOfLastWebApkUpdateRequestCompletion(); + storage.updateDidLastWebApkUpdateRequestSucceed(success); } private static native void nativeUpdateAsync(String id, String startUrl, String scope,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java index 7022ef3..7b22d9a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -60,8 +60,6 @@ protected WebappInfo mWebappInfo; - private boolean mOldWebappCleanupStarted; - private ViewGroup mSplashScreen; private WebappUrlBar mUrlBar; @@ -126,7 +124,23 @@ @Override public void preInflationStartup() { WebappInfo info = WebappInfo.create(getIntent()); - if (info != null) mWebappInfo = info; + + String id = ""; + if (info != null) { + mWebappInfo = info; + id = info.id(); + } + + // Initialize the WebappRegistry and warm up the shared preferences for this web app. No-ops + // if the registry and this web app are already initialized. Must override Strict Mode to + // avoid a violation. + StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); + try { + WebappRegistry.getInstance(); + WebappRegistry.warmUpSharedPrefsForId(id); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } ScreenOrientationProvider.lockOrientation((byte) mWebappInfo.orientation(), this); super.preInflationStartup(); @@ -195,13 +209,6 @@ updateTaskDescription(); } super.onResume(); - - // Kick off the old web app cleanup (if we haven't already) now that we have queued the - // current web app's storage to be opened. - if (!mOldWebappCleanupStarted) { - WebappRegistry.unregisterOldWebapps(System.currentTimeMillis()); - mOldWebappCleanupStarted = true; - } } @Override @@ -262,25 +269,20 @@ } protected void initializeSplashScreenWidgets(final int backgroundColor) { - WebappRegistry.getWebappDataStorage( - mWebappInfo.id(), new WebappRegistry.FetchWebappDataStorageCallback() { - @Override - public void onWebappDataStorageRetrieved(WebappDataStorage storage) { - if (storage == null) { - onStorageIsNull(backgroundColor); - return; - } - updateStorage(storage); + WebappDataStorage storage = + WebappRegistry.getInstance().getWebappDataStorage(mWebappInfo.id()); + if (storage == null) { + onStorageIsNull(backgroundColor); + return; + } - // Retrieve the splash image if it exists. - storage.getSplashScreenImage(new WebappDataStorage.FetchCallback<Bitmap>() { - @Override - public void onDataRetrieved(Bitmap splashImage) { - initializeSplashScreenWidgets(backgroundColor, splashImage); - } - }); - } - }); + updateStorage(storage); + storage.getSplashScreenImage(new WebappDataStorage.FetchCallback<Bitmap>() { + @Override + public void onDataRetrieved(Bitmap splashImage) { + initializeSplashScreenWidgets(backgroundColor, splashImage); + } + }); } protected void onStorageIsNull(int backgroundColor) {} @@ -567,7 +569,7 @@ @Override protected final ChromeFullscreenManager createFullscreenManager( ControlContainer controlContainer) { - return new ChromeFullscreenManager(this, controlContainer, getTabModelSelector(), + return new ChromeFullscreenManager(this, controlContainer, getControlContainerHeightResource(), false /* supportsBrowserOverride */); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java index 41f8f4d..32bed750 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java
@@ -19,7 +19,6 @@ import org.chromium.chrome.browser.util.IntentUtils; import org.chromium.content_public.common.ScreenOrientationValues; -import java.util.Map; import java.util.concurrent.TimeUnit; /** @@ -51,8 +50,7 @@ static final String KEY_LAST_CHECK_WEB_MANIFEST_UPDATE_TIME = "last_check_web_manifest_update_time"; - // The last time that the WebAPK update request completed (successfully or - // unsuccessfully). + // The last time that the WebAPK update request completed (successfully or unsuccessfully). static final String KEY_LAST_WEBAPK_UPDATE_REQUEST_COMPLETE_TIME = "last_webapk_update_request_complete_time"; @@ -60,8 +58,8 @@ static final String KEY_DID_LAST_WEBAPK_UPDATE_REQUEST_SUCCEED = "did_last_webapk_update_request_succeed"; - // Unset/invalid constants for last used times and URLs. 0 is used as the null last - // used time as WebappRegistry assumes that this is always a valid timestamp. + // Unset/invalid constants for last used times and URLs. 0 is used as the null last used time as + // WebappRegistry assumes that this is always a valid timestamp. static final long LAST_USED_UNSET = 0; static final long LAST_USED_INVALID = -1; static final String URL_INVALID = ""; @@ -79,119 +77,52 @@ private final SharedPreferences mPreferences; /** - * Opens an instance of WebappDataStorage for the web app specified. Must not be run on the UI - * thread. - * @param webappId The ID of the web app which is being opened. + * Called after data has been retrieved from storage. + */ + public interface FetchCallback<T> { + public void onDataRetrieved(T readObject); + } + + /** + * Factory used to generate WebappDataStorage objects. + * Overridden in tests to inject mocked objects. + */ + public static class Factory { + /** + * Generates a WebappDataStorage instance for a specified web app. + */ + public WebappDataStorage create(final String webappId) { + return new WebappDataStorage(webappId); + } + } + + /** + * Clock used to generate the current time in millseconds for setting last used time. + */ + public static class Clock { + /** + * @return Current time in milliseconds. + */ + public long currentTimeMillis() { + return System.currentTimeMillis(); + } + } + + /** + * Opens an instance of WebappDataStorage for the web app specified. + * @param webappId The ID of the web app. */ static WebappDataStorage open(final String webappId) { final WebappDataStorage storage = sFactory.create(webappId); if (storage.getLastUsedTime() == LAST_USED_INVALID) { // If the last used time is invalid then ensure that there is no data in the // WebappDataStorage which needs to be cleaned up. - assert storage.getAllData().isEmpty(); + assert storage.isEmpty(); } return storage; } /** - * Asynchronously retrieves the time which this WebappDataStorage was last opened. Used in - * testing. - * @param webappId The ID of the web app the used time is being read for. - * @param callback Called when the last used time has been retrieved. - */ - @VisibleForTesting - public static void getLastUsedTime(final String webappId, final FetchCallback<Long> callback) { - new AsyncTask<Void, Void, Long>() { - @Override - protected final Long doInBackground(Void... nothing) { - long lastUsed = new WebappDataStorage(webappId).getLastUsedTime(); - assert lastUsed != LAST_USED_INVALID; - return lastUsed; - } - - @Override - protected final void onPostExecute(Long lastUsed) { - assert callback != null; - callback.onDataRetrieved(lastUsed); - } - }.execute(); - } - - /** - * Asynchronously retrieves the scope stored in this WebappDataStorage. The scope is the URL - * over which the web app data is applied to. Used in testing. - * @param webappId The ID of the web app the used time is being read for. - * @param callback Called when the scope has been retrieved. - */ - @VisibleForTesting - public static void getScope(final String webappId, final FetchCallback<String> callback) { - new AsyncTask<Void, Void, String>() { - @Override - protected final String doInBackground(Void... nothing) { - return new WebappDataStorage(webappId).getScope(); - } - - @Override - protected final void onPostExecute(String scope) { - assert callback != null; - callback.onDataRetrieved(scope); - } - }.execute(); - } - - /** - * Asynchronously retrieves the URL stored in this WebappDataStorage. Used in testing. - * @param webappId The ID of the web app the used time is being read for. - * @param callback Called when the URL has been retrieved. - */ - @VisibleForTesting - public static void getUrl(final String webappId, final FetchCallback<String> callback) { - new AsyncTask<Void, Void, String>() { - @Override - protected final String doInBackground(Void... nothing) { - return new WebappDataStorage(webappId).getUrl(); - } - - @Override - protected final void onPostExecute(String url) { - assert callback != null; - callback.onDataRetrieved(url); - } - }.execute(); - } - - /** - * Deletes the data for a web app by clearing all the information inside the SharedPreferences - * file. This does NOT delete the file itself but the file is left empty. - * @param webappId The ID of the web app being deleted. - */ - static void deleteDataForWebapp(final String webappId) { - assert !ThreadUtils.runningOnUiThread(); - openSharedPreferences(webappId).edit().clear().apply(); - } - - /** - * Deletes the URL and scope, and sets all timestamps to 0 in SharedPreferences. - * This does not remove the stored splash screen image (if any) for the app. - * @param webappId The ID of the web app for which history is being cleared. - */ - static void clearHistory(final String webappId) { - assert !ThreadUtils.runningOnUiThread(); - SharedPreferences.Editor editor = openSharedPreferences(webappId).edit(); - - // The last used time is set to 0 to ensure that a valid value is always present. - // If the web app is not launched prior to the next cleanup, then its remaining data will be - // removed. Otherwise, the next launch from home screen will update the last used time. - editor.putLong(KEY_LAST_USED, LAST_USED_UNSET); - editor.remove(KEY_URL); - editor.remove(KEY_SCOPE); - editor.remove(KEY_LAST_CHECK_WEB_MANIFEST_UPDATE_TIME); - editor.remove(KEY_LAST_WEBAPK_UPDATE_REQUEST_COMPLETE_TIME); - editor.remove(KEY_DID_LAST_WEBAPK_UPDATE_REQUEST_SUCCEED); - editor.apply(); - } - - /** * Sets the clock used to get the current time. */ @VisibleForTesting @@ -207,20 +138,11 @@ sFactory = factory; } - private static SharedPreferences openSharedPreferences(String webappId) { - return ContextUtils.getApplicationContext().getSharedPreferences( - SHARED_PREFS_FILE_PREFIX + webappId, Context.MODE_PRIVATE); - } - - protected WebappDataStorage(String webappId) { - mId = webappId; - mPreferences = openSharedPreferences(webappId); - } - /** - * Asynchronously retrieves the splash screen image associated with the current web app. + * Asynchronously retrieves the splash screen image associated with the web app. The work is + * performed on a background thread as it requires a potentially expensive image decode. * @param callback Called when the splash screen image has been retrieved. - * The bitmap result may be null if no image was found. + * The bitmap result will be null if no image was found. */ public void getSplashScreenImage(final FetchCallback<Bitmap> callback) { new AsyncTask<Void, Void, Bitmap>() { @@ -239,36 +161,17 @@ } /** - * Update the information associated with the web app with the specified data. + * Update the splash screen image associated with the web app with the specified data. The image + * must have been encoded using {@link ShortcutHelper#encodeBitmapAsString}. * @param splashScreenImage The image which should be shown on the splash screen of the web app. */ - public void updateSplashScreenImage(final Bitmap splashScreenImage) { - // Use an AsyncTask as this method is invoked on the UI thread from the callbacks leading to - // ShortcutHelper.storeWebappSplashImage. - new AsyncTask<Void, Void, Void>() { - @Override - protected final Void doInBackground(Void... nothing) { - String bitmap = ShortcutHelper.encodeBitmapAsString(splashScreenImage); - mPreferences.edit().putString(KEY_SPLASH_ICON, bitmap).apply(); - return null; - } - }.execute(); - } - - /** - * Update the information associated with the web app with the specified data. Used for testing. - * @param splashScreenImage The image encoded as a string which should be shown on the splash - * screen of the web app. - */ - @VisibleForTesting - void updateSplashScreenImageForTests(String splashScreenImage) { + public void updateSplashScreenImage(String splashScreenImage) { mPreferences.edit().putString(KEY_SPLASH_ICON, splashScreenImage).apply(); } /** * Creates and returns a web app launch intent from the data stored in this object. Must not be - * called on the UI thread as a Bitmap is decoded from a String (a potentially expensive - * operation). + * called on the main thread as it requires a potentially expensive image decode. * @return The web app launch intent. */ public Intent createWebappLaunchIntent() { @@ -366,20 +269,73 @@ } /** + * Returns true if this web app has been launched from home screen recently (within + * WEBAPP_LAST_OPEN_MAX_TIME milliseconds). + */ + public boolean wasLaunchedRecently() { + // WebappRegistry.register sets the last used time, so that counts as a 'launch'. + return (sClock.currentTimeMillis() - getLastUsedTime() < WEBAPP_LAST_OPEN_MAX_TIME); + } + + /** + * Deletes the data for a web app by clearing all the information inside the SharedPreferences + * file. This does NOT delete the file itself but the file is left empty. + */ + void delete() { + mPreferences.edit().clear().apply(); + } + + /** + * Deletes the URL and scope, and sets all timestamps to 0 in SharedPreferences. + * This does not remove the stored splash screen image (if any) for the app. + */ + void clearHistory() { + SharedPreferences.Editor editor = mPreferences.edit(); + + // The last used time is set to 0 to ensure that a valid value is always present. + // If the web app is not launched prior to the next cleanup, then its remaining data will be + // removed. Otherwise, the next launch from home screen will update the last used time. + editor.putLong(KEY_LAST_USED, LAST_USED_UNSET); + editor.remove(KEY_URL); + editor.remove(KEY_SCOPE); + editor.remove(KEY_LAST_CHECK_WEB_MANIFEST_UPDATE_TIME); + editor.remove(KEY_LAST_WEBAPK_UPDATE_REQUEST_COMPLETE_TIME); + editor.remove(KEY_DID_LAST_WEBAPK_UPDATE_REQUEST_SUCCEED); + editor.apply(); + } + + /** * Returns the scope stored in this object, or URL_INVALID if it is not stored. */ - String getScope() { + public String getScope() { return mPreferences.getString(KEY_SCOPE, URL_INVALID); } /** * Returns the URL stored in this object, or URL_INVALID if it is not stored. */ - String getUrl() { + public String getUrl() { return mPreferences.getString(KEY_URL, URL_INVALID); } /** + * Returns the last used time of this object, or -1 if it is not stored. + */ + public long getLastUsedTime() { + return mPreferences.getLong(KEY_LAST_USED, LAST_USED_INVALID); + } + + /** + * Update the information associated with the web app with the specified data. Used for testing. + * @param splashScreenImage The image encoded as a string which should be shown on the splash + * screen of the web app. + */ + @VisibleForTesting + void updateSplashScreenImageForTests(String splashScreenImage) { + mPreferences.edit().putString(KEY_SPLASH_ICON, splashScreenImage).apply(); + } + + /** * Updates the last used time of this object. */ void updateLastUsedTime() { @@ -387,13 +343,6 @@ } /** - * Returns the last used time of this object, or -1 if it is not stored. - */ - long getLastUsedTime() { - return mPreferences.getLong(KEY_LAST_USED, LAST_USED_INVALID); - } - - /** * Returns the package name if the data is for a WebAPK, null otherwise. */ String getWebApkPackageName() { @@ -401,7 +350,7 @@ } /** - * Updates the time of the last check for whether the WebAPK's Web Manifest was updated. + * Updates the time of the last check for whether the WebAPK's Web Manifest was updated. */ void updateTimeOfLastCheckForUpdatedWebManifest() { mPreferences.edit() @@ -418,8 +367,7 @@ } /** - * Updates the time that the last WebAPK update request completed (successfully or - * unsuccessfully). + * Updates when the last WebAPK update request finished (successfully or unsuccessfully). */ void updateTimeOfLastWebApkUpdateRequestCompletion() { mPreferences.edit() @@ -428,8 +376,8 @@ } /** - * Returns the time that the last WebAPK update request completed (successfully or - * unsuccessfully). This time needs to be set when the WebAPK was registered. + * Returns when the last WebAPK update request completed (successfully or unsuccessfully). + * This time needs to be set when the WebAPK is registered. */ long getLastWebApkUpdateRequestCompletionTime() { return mPreferences.getLong( @@ -439,9 +387,9 @@ /** * Updates the result of whether the last update request to WebAPK Server succeeded. */ - void updateDidLastWebApkUpdateRequestSucceed(boolean sucess) { + void updateDidLastWebApkUpdateRequestSucceed(boolean success) { mPreferences.edit() - .putBoolean(KEY_DID_LAST_WEBAPK_UPDATE_REQUEST_SUCCEED, sucess) + .putBoolean(KEY_DID_LAST_WEBAPK_UPDATE_REQUEST_SUCCEED, success) .apply(); } @@ -452,51 +400,13 @@ return mPreferences.getBoolean(KEY_DID_LAST_WEBAPK_UPDATE_REQUEST_SUCCEED, false); } - /** - * Returns true if this web app has been launched from home screen recently (within - * WEBAPP_LAST_OPEN_MAX_TIME milliseconds). - */ - public boolean wasLaunchedRecently() { - // Registering the web app sets the last used time, so that counts as a 'launch'. - return (sClock.currentTimeMillis() - getLastUsedTime() < WEBAPP_LAST_OPEN_MAX_TIME); + protected WebappDataStorage(String webappId) { + mId = webappId; + mPreferences = ContextUtils.getApplicationContext().getSharedPreferences( + SHARED_PREFS_FILE_PREFIX + webappId, Context.MODE_PRIVATE); } - private Map<String, ?> getAllData() { - return mPreferences.getAll(); - } - - /** - * Called after data has been retrieved from storage. - */ - public interface FetchCallback<T> { - public void onDataRetrieved(T readObject); - } - - /** - * Factory used to generate WebappDataStorage objects. - * - * It is used in tests to override methods in WebappDataStorage and inject the mocked objects. - */ - public static class Factory { - - /** - * Generates a WebappDataStorage class for a specified web app. - */ - public WebappDataStorage create(final String webappId) { - return new WebappDataStorage(webappId); - } - } - - /** - * Clock used to generate the current time in millseconds for updating and setting last used - * time. - */ - public static class Clock { - /** - * Returns the current time in milliseconds. - */ - public long currentTimeMillis() { - return System.currentTimeMillis(); - } + private boolean isEmpty() { + return mPreferences.getAll().isEmpty(); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java index 4b2a901..5a2c9de 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java
@@ -14,7 +14,6 @@ import org.chromium.chrome.browser.ShortcutSource; import org.chromium.chrome.browser.util.IntentUtils; import org.chromium.content_public.common.ScreenOrientationValues; -import org.chromium.webapk.lib.common.WebApkConstants; /** * Stores info about a web app. @@ -58,58 +57,6 @@ return shortName == null ? titleFromIntent(intent) : shortName; } - public static int displayModeFromIntent(Intent intent) { - String displayMode = - IntentUtils.safeGetStringExtra(intent, WebApkConstants.EXTRA_WEBAPK_DISPLAY_MODE); - if (displayMode == null) { - return IntentUtils.safeGetIntExtra( - intent, ShortcutHelper.EXTRA_DISPLAY_MODE, WebDisplayMode.Standalone); - } - - // {@link displayMode} should be one of - // https://w3c.github.io/manifest/#dfn-display-modes-values - if (displayMode.equals("fullscreen")) { - return WebDisplayMode.Fullscreen; - } else if (displayMode.equals("minimal-ui")) { - return WebDisplayMode.MinimalUi; - } else if (displayMode.equals("browser")) { - return WebDisplayMode.Browser; - } else { - return WebDisplayMode.Standalone; - } - } - - public static int orientationFromIntent(Intent intent) { - String orientation = - IntentUtils.safeGetStringExtra(intent, WebApkConstants.EXTRA_WEBAPK_ORIENTATION); - if (orientation == null) { - return IntentUtils.safeGetIntExtra( - intent, ShortcutHelper.EXTRA_ORIENTATION, ScreenOrientationValues.DEFAULT); - } - - // {@link orientation} should be one of - // w3c.github.io/screen-orientation/#orientationlocktype-enum - if (orientation.equals("any")) { - return ScreenOrientationValues.ANY; - } else if (orientation.equals("natural")) { - return ScreenOrientationValues.NATURAL; - } else if (orientation.equals("landscape")) { - return ScreenOrientationValues.LANDSCAPE; - } else if (orientation.equals("landscape-primary")) { - return ScreenOrientationValues.LANDSCAPE_PRIMARY; - } else if (orientation.equals("landscape-secondary")) { - return ScreenOrientationValues.LANDSCAPE_SECONDARY; - } else if (orientation.equals("portrait")) { - return ScreenOrientationValues.PORTRAIT; - } else if (orientation.equals("portrait-primary")) { - return ScreenOrientationValues.PORTRAIT_PRIMARY; - } else if (orientation.equals("portrait-secondary")) { - return ScreenOrientationValues.PORTRAIT_SECONDARY; - } else { - return ScreenOrientationValues.DEFAULT; - } - } - /** * Construct a WebappInfo. * @param intent Intent containing info about the app. @@ -119,8 +66,10 @@ String icon = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_ICON); String url = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_URL); String scope = IntentUtils.safeGetStringExtra(intent, ShortcutHelper.EXTRA_SCOPE); - int displayMode = displayModeFromIntent(intent); - int orientation = orientationFromIntent(intent); + int displayMode = IntentUtils.safeGetIntExtra( + intent, ShortcutHelper.EXTRA_DISPLAY_MODE, WebDisplayMode.Standalone); + int orientation = IntentUtils.safeGetIntExtra( + intent, ShortcutHelper.EXTRA_ORIENTATION, ScreenOrientationValues.DEFAULT); int source = IntentUtils.safeGetIntExtra(intent, ShortcutHelper.EXTRA_SOURCE, ShortcutSource.UNKNOWN); long themeColor = IntentUtils.safeGetLongExtra(intent, @@ -153,6 +102,7 @@ * @param orientation Orientation of the webapp. * @param source Source where the webapp was added from. * @param themeColor The theme color of the webapp. + * @param backgroundColor The background color of the webapp. * @param isIconGenerated Whether the |icon| was generated by Chromium. * @param webApkPackageName The package of the WebAPK associated with the webapp. Null if * no WebAPK is associated with the webapp.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java index cdd3ab6..06c1fba 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java
@@ -63,6 +63,19 @@ ChromeWebApkHost.init(); boolean isValidWebApk = isValidWebApk(webApkPackageName, webappUrl); + if (isValidWebApk) { + // {@link #isValidWebApk} checks whether the start URL sent in the intent is in the + // scope of a WebAPK but it does not check that the intent was sent from Chrome. Unlike + // non-WebAPK web apps, WebAPK ids are predictable. A malicious actor may send an intent + // with a valid start URL and arbitrary other data. Only use the start URL, the package + // name and the ShortcutSource from the launch intent and extract the remaining data + // from the <meta-data> in the WebAPK's Android manifest. + webappInfo = WebApkMetaDataUtils.extractWebappInfoFromWebApk( + webApkPackageName, webappUrl, webappInfo.source()); + + if (webappInfo == null) return; + } + // Permit the launch to a standalone web app frame if any of the following are true: // - the request was for a WebAPK that is valid; // - the MAC is present and valid for the homescreen shortcut to be opened;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java index 629aef6..2f4d265 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java
@@ -11,25 +11,31 @@ import android.os.AsyncTask; import org.chromium.base.ContextUtils; -import org.chromium.base.ThreadUtils; import org.chromium.base.VisibleForTesting; import org.chromium.base.annotations.CalledByNative; import org.chromium.chrome.browser.browsing_data.UrlFilter; import org.chromium.chrome.browser.browsing_data.UrlFilterBridge; import java.util.Collections; -import java.util.HashSet; +import java.util.HashMap; +import java.util.Iterator; import java.util.Set; import java.util.concurrent.TimeUnit; /** - * Keeps track of web apps which have created a SharedPreference file (through the used of the - * WebappDataStorage class) which may need to be cleaned up in the future. + * Singleton class which tracks web apps backed by a SharedPreferences file (abstracted by the + * WebappDataStorage class). This class must be used on the main thread, except when warming + * SharedPreferences. * - * It is NOT intended to be 100% accurate nor a comprehensive list of all installed web apps - * because it is impossible to track when the user removes a web app from the Home screen and it - * is similarily impossible to track pre-registry era web apps (this case is not a problem anyway - * as these web apps have no external data to cleanup). + * Aside from web app registration, which is asynchronous as a new SharedPreferences file must be + * opened, all methods in this class are synchronous. All web app SharedPreferences known to + * WebappRegistry are pre-warmed on browser startup when creating the singleton WebappRegistry + * instance, whilst registering a new web app will automatically cache the new SharedPreferences + * after it is created. + * + * This class is not a comprehensive list of installed web apps because it is impossible to know + * when the user removes a web app from the home screen. The WebappDataStorage.wasLaunchedRecently() + * heuristic attempts to compensate for this. */ public class WebappRegistry { @@ -43,281 +49,214 @@ /** Represents a period of 13 weeks in milliseconds */ static final long WEBAPP_UNOPENED_CLEANUP_DURATION = TimeUnit.DAYS.toMillis(13L * 7L); - /** - * Called when a retrieval of the set of stored web app IDs occurs. - */ - public interface FetchCallback { - void onWebappIdsRetrieved(Set<String> readObject); - } + private static volatile WebappRegistry sInstance; + + private HashMap<String, WebappDataStorage> mStorages; + private SharedPreferences mPreferences; /** - * Called when a retrieval of the stored WebappDataStorage occurs. The storage parameter will - * be null if the web app queried for was not in the registry. + * Callback run when a WebappDataStorage object is registered for the first time. The storage + * parameter will never be null. */ public interface FetchWebappDataStorageCallback { void onWebappDataStorageRetrieved(WebappDataStorage storage); } /** + * Returns the singleton WebappRegistry instance. Creates the instance if necessary. + */ + public static WebappRegistry getInstance() { + if (sInstance == null) sInstance = new WebappRegistry(); + return sInstance; + } + + /** + * Warm up the WebappRegistry and a specific WebappDataStorage SharedPreferences. This static + * method can be called on any thread, so it must not initialize sInstance. + * @param id The web app id to warm up in addition to the WebappRegistry. + */ + public static void warmUpSharedPrefsForId(String id) { + sInstance.initStorages(id, false); + } + + /** + * Warm up the WebappRegistry and all WebappDataStorage SharedPreferences. This static method + * can be called on any thread, so it must not initialize sInstance. + */ + public static void warmUpSharedPrefs() { + sInstance.initStorages(null, false); + } + + public static void refreshSharedPrefsForTesting() { + sInstance = new WebappRegistry(); + sInstance.initStorages(null, true); + } + + /** * Registers the existence of a web app, creates a SharedPreference entry for it, and runs the * supplied callback (if not null) on the UI thread with the resulting WebappDataStorage object. * @param webappId The id of the web app to register. * @param callback The callback to run with the WebappDataStorage argument. * @return The storage object for the web app. */ - public static void registerWebapp(final String webappId, - final FetchWebappDataStorageCallback callback) { + public void register(final String webappId, final FetchWebappDataStorageCallback callback) { new AsyncTask<Void, Void, WebappDataStorage>() { @Override protected final WebappDataStorage doInBackground(Void... nothing) { - SharedPreferences preferences = openSharedPreferences(); - // The set returned by getRegisteredWebappIds must be treated as immutable, so we - // make a copy to edit and save. - Set<String> webapps = new HashSet<>(getRegisteredWebappIds(preferences)); - boolean added = webapps.add(webappId); - assert added; - - preferences.edit().putStringSet(KEY_WEBAPP_SET, webapps).apply(); - - // Create the WebappDataStorage and update the last used time, so we can guarantee - // that a web app which appears in the registry will have a - // last used time != WebappDataStorage.LAST_USED_INVALID. - WebappDataStorage storage = new WebappDataStorage(webappId); - storage.updateLastUsedTime(); - return storage; + // Create the WebappDataStorage on the background thread, as this must create and + // open a new SharedPreferences. + return WebappDataStorage.open(webappId); } @Override protected final void onPostExecute(WebappDataStorage storage) { + // Guarantee that last used time != WebappDataStorage.LAST_USED_INVALID. Must be + // run on the main thread as SharedPreferences.Editor.apply() is called. + mStorages.put(webappId, storage); + mPreferences.edit().putStringSet(KEY_WEBAPP_SET, mStorages.keySet()).apply(); + storage.updateLastUsedTime(); if (callback != null) callback.onWebappDataStorageRetrieved(storage); } }.execute(); } /** - * Runs the callback, supplying the WebappDataStorage object for webappId, or null if the web - * app has not been registered. - * @param webappId The id of the web app to register. + * Returns the WebappDataStorage object for webappId, or null if one cannot be found. + * @param webappId The id of the web app. * @return The storage object for the web app, or null if webappId is not registered. */ - public static void getWebappDataStorage(final String webappId, - final FetchWebappDataStorageCallback callback) { - new AsyncTask<Void, Void, WebappDataStorage>() { - @Override - protected final WebappDataStorage doInBackground(Void... nothing) { - SharedPreferences preferences = openSharedPreferences(); - if (getRegisteredWebappIds(preferences).contains(webappId)) { - WebappDataStorage storage = WebappDataStorage.open(webappId); - return storage; - } - return null; - } - - @Override - protected final void onPostExecute(WebappDataStorage storage) { - assert callback != null; - callback.onWebappDataStorageRetrieved(storage); - } - }.execute(); + public WebappDataStorage getWebappDataStorage(String webappId) { + return mStorages.get(webappId); } /** - * Runs the callback, supplying the WebappDataStorage object whose scope most closely matches - * the provided URL, or null if a matching web app cannot be found. The most closely matching - * scope is the longest scope which has the same prefix as the URL to open. - * @param url The URL to search for. - * @return The storage object for the web app, or null if webappId is not registered. + * Returns the WebappDataStorage object whose scope most closely matches the provided URL, or + * null if a matching web app cannot be found. The most closely matching scope is the longest + * scope which has the same prefix as the URL to open. + * @param url The URL to search for. + * @return The storage object for the web app, or null if one cannot be found. */ - public static void getWebappDataStorageForUrl(final String url, - final FetchWebappDataStorageCallback callback) { - new AsyncTask<Void, Void, WebappDataStorage>() { - @Override - protected final WebappDataStorage doInBackground(Void... nothing) { - SharedPreferences preferences = openSharedPreferences(); - WebappDataStorage bestMatch = null; - int largestOverlap = 0; - for (String id : getRegisteredWebappIds(preferences)) { - WebappDataStorage storage = WebappDataStorage.open(id); - String scope = storage.getScope(); - if (url.startsWith(scope) && scope.length() > largestOverlap) { - bestMatch = storage; - largestOverlap = scope.length(); - } - } - return bestMatch; + public WebappDataStorage getWebappDataStorageForUrl(final String url) { + WebappDataStorage bestMatch = null; + int largestOverlap = 0; + for (HashMap.Entry<String, WebappDataStorage> entry : mStorages.entrySet()) { + WebappDataStorage storage = entry.getValue(); + String scope = storage.getScope(); + if (url.startsWith(scope) && scope.length() > largestOverlap) { + bestMatch = storage; + largestOverlap = scope.length(); } - - protected final void onPostExecute(WebappDataStorage storage) { - assert callback != null; - callback.onWebappDataStorageRetrieved(storage); - } - }.execute(); + } + return bestMatch; } /** - * Asynchronously retrieves the list of web app IDs which this registry is aware of. - * @param callback Called when the set has been retrieved. The set may be empty. + * Returns the list of web app IDs which are written to SharedPreferences. */ @VisibleForTesting - public static void getRegisteredWebappIds(final FetchCallback callback) { - new AsyncTask<Void, Void, Set<String>>() { - @Override - protected final Set<String> doInBackground(Void... nothing) { - return getRegisteredWebappIds(openSharedPreferences()); - } - - @Override - protected final void onPostExecute(Set<String> result) { - assert callback != null; - callback.onWebappIdsRetrieved(result); - } - }.execute(); + public static Set<String> getRegisteredWebappIdsForTesting() { + // Wrap with unmodifiableSet to ensure it's never modified. See crbug.com/568369. + return Collections.unmodifiableSet(openSharedPreferences().getStringSet( + KEY_WEBAPP_SET, Collections.<String>emptySet())); } /** - * 1. Deletes the data for all "old" web apps. - * "Old" web apps have not been opened by the user in the last 3 months, or have had their last - * used time set to 0 by the user clearing their history. Cleanup is run, at most, once a month. - * 2. Deletes the data for all WebAPKs that have been uninstalled in the last month. - * + * Deletes the data for all "old" web apps, as well as all WebAPKs that have been uninstalled in + * the last month. "Old" web apps have not been opened by the user in the last 3 months, or have + * had their last used time set to 0 by the user clearing their history. Cleanup is run, at + * most, once a month. * @param currentTime The current time which will be checked to decide if the task should be run * and if a web app should be cleaned up. */ - static void unregisterOldWebapps(final long currentTime) { - new AsyncTask<Void, Void, Void>() { - @Override - protected final Void doInBackground(Void... nothing) { - SharedPreferences preferences = openSharedPreferences(); - long lastCleanup = preferences.getLong(KEY_LAST_CLEANUP, 0); - if ((currentTime - lastCleanup) < FULL_CLEANUP_DURATION) return null; - - Set<String> currentWebapps = getRegisteredWebappIds(preferences); - Set<String> retainedWebapps = new HashSet<>(currentWebapps); - PackageManager pm = ContextUtils.getApplicationContext().getPackageManager(); - for (String id : currentWebapps) { - WebappDataStorage storage = new WebappDataStorage(id); - String webApkPackage = storage.getWebApkPackageName(); - if (webApkPackage != null) { - if (isWebApkInstalled(pm, webApkPackage)) continue; - } else { - long lastUsed = storage.getLastUsedTime(); - if ((currentTime - lastUsed) < WEBAPP_UNOPENED_CLEANUP_DURATION) continue; - } - WebappDataStorage.deleteDataForWebapp(id); - retainedWebapps.remove(id); - } - - preferences.edit() - .putLong(KEY_LAST_CLEANUP, currentTime) - .putStringSet(KEY_WEBAPP_SET, retainedWebapps) - .apply(); - return null; - } - }.execute(); - } - - /** - * Returns whether the given WebAPK is still installed. - */ - private static boolean isWebApkInstalled(PackageManager pm, String webApkPackage) { - assert !ThreadUtils.runningOnUiThread(); - try { - pm.getPackageInfo(webApkPackage, PackageManager.GET_ACTIVITIES); - } catch (NameNotFoundException e) { - return false; + public void unregisterOldWebapps(long currentTime) { + if ((currentTime - mPreferences.getLong(KEY_LAST_CLEANUP, 0)) < FULL_CLEANUP_DURATION) { + return; } - return true; + + Iterator<HashMap.Entry<String, WebappDataStorage>> it = mStorages.entrySet().iterator(); + while (it.hasNext()) { + HashMap.Entry<String, WebappDataStorage> entry = it.next(); + WebappDataStorage storage = entry.getValue(); + String webApkPackage = storage.getWebApkPackageName(); + if (webApkPackage != null) { + if (isWebApkInstalled(webApkPackage)) { + continue; + } + } else if ((currentTime - storage.getLastUsedTime()) + < WEBAPP_UNOPENED_CLEANUP_DURATION) { + continue; + } + storage.delete(); + it.remove(); + } + + mPreferences.edit() + .putLong(KEY_LAST_CLEANUP, currentTime) + .putStringSet(KEY_WEBAPP_SET, mStorages.keySet()) + .apply(); } /** - * Deletes the data of all web apps whose url matches |urlFilter|, as well as the registry - * tracking those web apps. + * Deletes the data of all web apps whose url matches |urlFilter|. + * @param urlFilter The filter object to check URLs. */ @VisibleForTesting - static void unregisterWebappsForUrls(final UrlFilter urlFilter, final Runnable callback) { - new AsyncTask<Void, Void, Void>() { - @Override - protected final Void doInBackground(Void... nothing) { - SharedPreferences preferences = openSharedPreferences(); - Set<String> registeredWebapps = - new HashSet<>(getRegisteredWebappIds(preferences)); - Set<String> webappsToUnregister = new HashSet<>(); - for (String id : registeredWebapps) { - if (urlFilter.matchesUrl(WebappDataStorage.open(id).getUrl())) { - WebappDataStorage.deleteDataForWebapp(id); - webappsToUnregister.add(id); - } - } - - // TODO(dominickn): SharedPreferences should be accessed on the main thread, not - // from an AsyncTask. Simultaneous access from two threads creates a race condition. - // Update all callsites in this class. - registeredWebapps.removeAll(webappsToUnregister); - if (registeredWebapps.isEmpty()) { - preferences.edit().clear().apply(); - } else { - preferences.edit().putStringSet(KEY_WEBAPP_SET, registeredWebapps).apply(); - } - - return null; + void unregisterWebappsForUrlsImpl(UrlFilter urlFilter) { + Iterator<HashMap.Entry<String, WebappDataStorage>> it = mStorages.entrySet().iterator(); + while (it.hasNext()) { + HashMap.Entry<String, WebappDataStorage> entry = it.next(); + WebappDataStorage storage = entry.getValue(); + if (urlFilter.matchesUrl(storage.getUrl())) { + storage.delete(); + it.remove(); } + } - @Override - protected final void onPostExecute(Void nothing) { - assert callback != null; - callback.run(); - } - }.execute(); + if (mStorages.isEmpty()) { + mPreferences.edit().clear().apply(); + } else { + mPreferences.edit().putStringSet(KEY_WEBAPP_SET, mStorages.keySet()).apply(); + } } @CalledByNative - static void unregisterWebappsForUrls( - final UrlFilterBridge urlFilter, final long callbackPointer) { - unregisterWebappsForUrls(urlFilter, new Runnable() { - @Override - public void run() { - urlFilter.destroy(); - nativeOnWebappsUnregistered(callbackPointer); - } - }); + static void unregisterWebappsForUrls(UrlFilterBridge urlFilter) { + WebappRegistry.getInstance().unregisterWebappsForUrlsImpl(urlFilter); + urlFilter.destroy(); } /** * Deletes the URL and scope, and sets the last used time to 0 for all web apps whose url * matches |urlFilter|. + * @param urlFilter The filter object to check URLs. */ @VisibleForTesting - static void clearWebappHistoryForUrls(final UrlFilter urlFilter, final Runnable callback) { - new AsyncTask<Void, Void, Void>() { - @Override - protected final Void doInBackground(Void... nothing) { - SharedPreferences preferences = openSharedPreferences(); - for (String id : getRegisteredWebappIds(preferences)) { - if (urlFilter.matchesUrl(WebappDataStorage.open(id).getUrl())) { - WebappDataStorage.clearHistory(id); - } - } - return null; + void clearWebappHistoryForUrlsImpl(UrlFilter urlFilter) { + for (HashMap.Entry<String, WebappDataStorage> entry : mStorages.entrySet()) { + WebappDataStorage storage = entry.getValue(); + if (urlFilter.matchesUrl(storage.getUrl())) { + storage.clearHistory(); } - - @Override - protected final void onPostExecute(Void nothing) { - assert callback != null; - callback.run(); - } - }.execute(); + } } @CalledByNative - static void clearWebappHistoryForUrls( - final UrlFilterBridge urlFilter, final long callbackPointer) { - clearWebappHistoryForUrls(urlFilter, new Runnable() { - @Override - public void run() { - urlFilter.destroy(); - nativeOnClearedWebappHistory(callbackPointer); - } - }); + static void clearWebappHistoryForUrls(UrlFilterBridge urlFilter) { + WebappRegistry.getInstance().clearWebappHistoryForUrlsImpl(urlFilter); + urlFilter.destroy(); + } + + /** + * Returns true if the given WebAPK is installed. + */ + private boolean isWebApkInstalled(String webApkPackage) { + try { + ContextUtils.getApplicationContext().getPackageManager().getPackageInfo( + webApkPackage, PackageManager.GET_ACTIVITIES); + } catch (NameNotFoundException e) { + return false; + } + return true; } private static SharedPreferences openSharedPreferences() { @@ -325,15 +264,28 @@ REGISTRY_FILE_NAME, Context.MODE_PRIVATE); } - private static Set<String> getRegisteredWebappIds(SharedPreferences preferences) { - // Wrap with unmodifiableSet to ensure it's never modified. See crbug.com/568369. - return Collections.unmodifiableSet( - preferences.getStringSet(KEY_WEBAPP_SET, Collections.<String>emptySet())); - } - private WebappRegistry() { + mPreferences = openSharedPreferences(); + mStorages = new HashMap<String, WebappDataStorage>(); } - private static native void nativeOnWebappsUnregistered(long callbackPointer); - private static native void nativeOnClearedWebappHistory(long callbackPointer); + private void initStorages(String idToInitialize, boolean replaceExisting) { + Set<String> webapps = + mPreferences.getStringSet(KEY_WEBAPP_SET, Collections.<String>emptySet()); + boolean initAll = (idToInitialize == null || idToInitialize.isEmpty()); + + // Don't overwrite any entry in mStorages unless replaceExisting is set to true. + if (initAll) { + for (String id : webapps) { + if (replaceExisting || !mStorages.containsKey(id)) { + mStorages.put(id, WebappDataStorage.open(id)); + } + } + } else { + if (webapps.contains(idToInitialize) + && (replaceExisting || !mStorages.containsKey(idToInitialize))) { + mStorages.put(idToInitialize, WebappDataStorage.open(idToInitialize)); + } + } + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java index 310953b..95232c3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java
@@ -157,11 +157,11 @@ /** * Prepare the progress bar for being attached to the window. - * @param toolbarHeight The height of the toolbar. + * @param topMargin The progress bar's top margin. */ - public void prepareForAttach(int toolbarHeight) { + public void prepareForAttach(int topMargin) { LayoutParams curParams = new LayoutParams(getLayoutParams()); - mMarginTop = toolbarHeight - curParams.height; + mMarginTop = topMargin; curParams.topMargin = mMarginTop; setLayoutParams(curParams); }
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index e9185f68..5c28eaf 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -949,6 +949,7 @@ "java/src/org/chromium/chrome/browser/tabmodel/document/StorageDelegate.java", "java/src/org/chromium/chrome/browser/tabmodel/document/TabDelegate.java", "java/src/org/chromium/chrome/browser/toolbar/ActionModeController.java", + "java/src/org/chromium/chrome/browser/toolbar/BottomToolbarPhone.java", "java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java", "java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbarAnimationDelegate.java", "java/src/org/chromium/chrome/browser/toolbar/HomePageButton.java", @@ -1005,6 +1006,7 @@ "java/src/org/chromium/chrome/browser/webapps/WebApkActivity9.java", "java/src/org/chromium/chrome/browser/webapps/WebApkInstaller.java", "java/src/org/chromium/chrome/browser/webapps/WebApkManagedActivity.java", + "java/src/org/chromium/chrome/browser/webapps/WebApkMetaDataUtils.java", "java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java", "java/src/org/chromium/chrome/browser/webapps/WebApkVersionManager.java", "java/src/org/chromium/chrome/browser/webapps/WebappActivity.java", @@ -1378,6 +1380,7 @@ "javatests/src/org/chromium/chrome/browser/webapps/ActivityAssignerTest.java", "javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenDialogTest.java", "javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenManagerTest.java", + "javatests/src/org/chromium/chrome/browser/webapps/TestFetchStorageCallback.java", "javatests/src/org/chromium/chrome/browser/webapps/ManifestUpgradeDetectorFetcherTest.java", "javatests/src/org/chromium/chrome/browser/webapps/ManifestUpgradeDetectorTest.java", "javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTestBase.java", @@ -1455,6 +1458,7 @@ "junit/src/org/chromium/chrome/browser/webapps/ManifestUpgradeDetectorTest.java", "junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java", "junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java", + "junit/src/org/chromium/chrome/browser/webapps/WebApkMetaDataUtilsTest.java", ] sync_shell_test_java_sources = [
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java index 4e2e9fe0..f008b18 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
@@ -128,7 +128,7 @@ } private static class TestDataStorageFactory extends WebappDataStorage.Factory { - public Bitmap mSplashImage; + public String mSplashImage; @Override public WebappDataStorage create(final String webappId) { @@ -142,7 +142,7 @@ } @Override - public void updateSplashScreenImage(Bitmap splashScreenImage) { + public void updateSplashScreenImage(String splashScreenImage) { assertNull(mSplashImage); mSplashImage = splashScreenImage; } @@ -539,7 +539,8 @@ // Test that bitmap sizes match expectations. int idealSize = getActivity().getResources().getDimensionPixelSize( R.dimen.webapp_splash_image_size_ideal); - assertEquals(idealSize, dataStorageFactory.mSplashImage.getWidth()); - assertEquals(idealSize, dataStorageFactory.mSplashImage.getHeight()); + Bitmap splashImage = ShortcutHelper.decodeBitmapFromString(dataStorageFactory.mSplashImage); + assertEquals(idealSize, splashImage.getWidth()); + assertEquals(idealSize, splashImage.getHeight()); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java index 434c989..7b4a76b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java
@@ -14,7 +14,7 @@ import org.chromium.chrome.browser.ShortcutHelper; import org.chromium.chrome.browser.preferences.PrefServiceBridge; import org.chromium.chrome.browser.preferences.PrefServiceBridge.OnClearBrowsingDataListener; -import org.chromium.chrome.browser.webapps.WebappDataStorage; +import org.chromium.chrome.browser.webapps.TestFetchStorageCallback; import org.chromium.chrome.browser.webapps.WebappRegistry; import org.chromium.chrome.test.ChromeActivityTestCaseBase; import org.chromium.content.browser.test.util.Criteria; @@ -24,7 +24,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; -import java.util.Set; /** * Integration tests for the native BrowsingDataRemover. @@ -67,18 +66,12 @@ return ShortcutHelper.createWebappShortcutIntentForTesting(webappId, webappUrl); } }; + final Intent shortcutIntent = shortcutIntentTask.execute().get(); - - WebappRegistry.registerWebapp( - webappId, new WebappRegistry.FetchWebappDataStorageCallback() { - @Override - public void onWebappDataStorageRetrieved(WebappDataStorage storage) { - storage.updateFromShortcutIntent(shortcutIntent); - mCallbackCalled = true; - } - }); - - CriteriaHelper.pollUiThread(new CallbackCriteria()); + TestFetchStorageCallback callback = new TestFetchStorageCallback(); + WebappRegistry.getInstance().register(webappId, callback); + callback.waitForCallback(0); + callback.getStorage().updateFromShortcutIntent(shortcutIntent); } /** @@ -98,16 +91,7 @@ for (final Map.Entry<String, String> app : apps.entrySet()) { registerWebapp(app.getKey(), app.getValue()); } - - // Wait for the registration to finish. - WebappRegistry.getRegisteredWebappIds(new WebappRegistry.FetchCallback() { - @Override - public void onWebappIdsRetrieved(Set<String> ids) { - assertEquals(apps.keySet(), ids); - mCallbackCalled = true; - } - }); - CriteriaHelper.pollUiThread(new CallbackCriteria()); + assertEquals(apps.keySet(), WebappRegistry.getRegisteredWebappIdsForTesting()); // Clear cookies and site data excluding the registrable domain "google.com". ThreadUtils.runOnUiThreadBlocking(new Runnable() { @@ -131,14 +115,8 @@ CriteriaHelper.pollUiThread(new CallbackCriteria()); // The last two webapps should have been unregistered. - WebappRegistry.getRegisteredWebappIds(new WebappRegistry.FetchCallback() { - @Override - public void onWebappIdsRetrieved(Set<String> ids) { - assertEquals(new HashSet<String>(Arrays.asList("webapp1")), ids); - mCallbackCalled = true; - } - }); - CriteriaHelper.pollUiThread(new CallbackCriteria()); + assertEquals(new HashSet<String>(Arrays.asList("webapp1")), + WebappRegistry.getRegisteredWebappIdsForTesting()); // Clear cookies and site data with no url filter. ThreadUtils.runOnUiThreadBlocking(new Runnable() { @@ -158,13 +136,6 @@ CriteriaHelper.pollUiThread(new CallbackCriteria()); // All webapps should have been unregistered. - WebappRegistry.getRegisteredWebappIds(new WebappRegistry.FetchCallback() { - @Override - public void onWebappIdsRetrieved(Set<String> ids) { - assertTrue(ids.isEmpty()); - mCallbackCalled = true; - } - }); - CriteriaHelper.pollUiThread(new CallbackCriteria()); + assertTrue(WebappRegistry.getRegisteredWebappIdsForTesting().isEmpty()); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicyTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicyTest.java index 21f4f496..977c1b3 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicyTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicyTest.java
@@ -385,6 +385,10 @@ } @Override + public void notifyStateLoaded(int tabCountAtStartup) { + } + + @Override public void destroy() { }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/PreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/PreferencesTest.java index a3dc2de..13e7804 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/PreferencesTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/PreferencesTest.java
@@ -16,6 +16,7 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.FlakyTest; import org.chromium.base.test.util.RetryOnFailure; import org.chromium.chrome.browser.accessibility.FontSizePrefs; import org.chromium.chrome.browser.preferences.website.ContentSetting; @@ -138,8 +139,12 @@ * Make sure that when a user switches to a search engine that uses HTTP, the location * permission is not added. */ - @SmallTest - @Feature({"Preferences"}) + /* + * @SmallTest + * @Feature({"Preferences"}) + * BUG=crbug.com/540706 + */ + @FlakyTest @DisableIf.Build(hardware_is = "sprout", message = "fails on android-one: crbug.com/540706") public void testSearchEnginePreferenceHttp() throws Exception { ensureTemplateUrlServiceLoaded();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java index d0f487b..7065600cb 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java
@@ -28,6 +28,7 @@ import org.chromium.chrome.browser.preferences.PrefServiceBridge; import org.chromium.chrome.browser.preferences.Preferences; import org.chromium.chrome.browser.preferences.privacy.ClearBrowsingDataPreferences.DialogOption; +import org.chromium.chrome.browser.webapps.TestFetchStorageCallback; import org.chromium.chrome.browser.webapps.WebappDataStorage; import org.chromium.chrome.browser.webapps.WebappRegistry; import org.chromium.chrome.test.ChromeActivityTestCaseBase; @@ -40,7 +41,6 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; -import java.util.Set; /** * Integration tests for ClearBrowsingDataPreferences. @@ -49,22 +49,6 @@ public class ClearBrowsingDataPreferencesTest extends ChromeActivityTestCaseBase<ChromeActivity> { private EmbeddedTestServer mTestServer; - private boolean mCallbackCalled; - - private class CallbackCriteria extends Criteria { - public CallbackCriteria() { - mCallbackCalled = false; - } - - @Override - public boolean isSatisfied() { - if (mCallbackCalled) { - mCallbackCalled = false; - return true; - } - return false; - } - } @Override protected void setUp() throws Exception { @@ -105,15 +89,11 @@ */ @MediumTest public void testClearingSiteDataClearsWebapps() throws Exception { - WebappRegistry.registerWebapp("first", null); - WebappRegistry.getRegisteredWebappIds(new WebappRegistry.FetchCallback() { - @Override - public void onWebappIdsRetrieved(Set<String> ids) { - assertEquals(new HashSet<String>(Arrays.asList("first")), ids); - mCallbackCalled = true; - } - }); - CriteriaHelper.pollUiThread(new CallbackCriteria()); + TestFetchStorageCallback callback = new TestFetchStorageCallback(); + WebappRegistry.getInstance().register("first", callback); + callback.waitForCallback(0); + assertEquals(new HashSet<String>(Arrays.asList("first")), + WebappRegistry.getRegisteredWebappIdsForTesting()); setDataTypesToClear(Arrays.asList(DialogOption.CLEAR_COOKIES_AND_SITE_DATA)); final ClearBrowsingDataPreferences preferences = @@ -132,14 +112,7 @@ }); waitForProgressToComplete(preferences); - WebappRegistry.getRegisteredWebappIds(new WebappRegistry.FetchCallback() { - @Override - public void onWebappIdsRetrieved(Set<String> ids) { - assertTrue(ids.isEmpty()); - mCallbackCalled = true; - } - }); - CriteriaHelper.pollUiThread(new CallbackCriteria()); + assertTrue(WebappRegistry.getRegisteredWebappIdsForTesting().isEmpty()); } /** @@ -156,23 +129,13 @@ }; final Intent shortcutIntent = shortcutIntentTask.execute().get(); - WebappRegistry.registerWebapp("first", new WebappRegistry.FetchWebappDataStorageCallback() { - @Override - public void onWebappDataStorageRetrieved(WebappDataStorage storage) { - storage.updateFromShortcutIntent(shortcutIntent); - mCallbackCalled = true; - } - }); - CriteriaHelper.pollUiThread(new CallbackCriteria()); + TestFetchStorageCallback callback = new TestFetchStorageCallback(); + WebappRegistry.getInstance().register("first", callback); + callback.waitForCallback(0); + callback.getStorage().updateFromShortcutIntent(shortcutIntent); - WebappRegistry.getRegisteredWebappIds(new WebappRegistry.FetchCallback() { - @Override - public void onWebappIdsRetrieved(Set<String> ids) { - assertEquals(new HashSet<String>(Arrays.asList("first")), ids); - mCallbackCalled = true; - } - }); - CriteriaHelper.pollUiThread(new CallbackCriteria()); + assertEquals(new HashSet<String>(Arrays.asList("first")), + WebappRegistry.getRegisteredWebappIdsForTesting()); setDataTypesToClear(Arrays.asList(DialogOption.CLEAR_HISTORY)); final ClearBrowsingDataPreferences preferences = @@ -191,45 +154,14 @@ }); waitForProgressToComplete(preferences); - // The web app should still exist in the registry. - WebappRegistry.getRegisteredWebappIds(new WebappRegistry.FetchCallback() { - @Override - public void onWebappIdsRetrieved(Set<String> ids) { - assertEquals(new HashSet<String>(Arrays.asList("first")), ids); - mCallbackCalled = true; - } - }); - CriteriaHelper.pollUiThread(new CallbackCriteria()); + assertEquals(new HashSet<String>(Arrays.asList("first")), + WebappRegistry.getRegisteredWebappIdsForTesting()); - // URL and scope should be empty. - WebappDataStorage.getScope("first", new WebappDataStorage.FetchCallback<String>() { - @Override - public void onDataRetrieved(String readObject) { - assertEquals(readObject, ""); - mCallbackCalled = true; - } - }); - CriteriaHelper.pollUiThread(new CallbackCriteria()); - - WebappDataStorage.getUrl("first", new WebappDataStorage.FetchCallback<String>() { - @Override - public void onDataRetrieved(String readObject) { - assertEquals(readObject, ""); - mCallbackCalled = true; - } - }); - CriteriaHelper.pollUiThread(new CallbackCriteria()); - - // The last used time should be 0. - WebappDataStorage.getLastUsedTime("first", new WebappDataStorage.FetchCallback<Long>() { - @Override - public void onDataRetrieved(Long readObject) { - long lastUsed = readObject; - assertEquals(lastUsed, 0); - mCallbackCalled = true; - } - }); - CriteriaHelper.pollUiThread(new CallbackCriteria()); + // URL and scope should be empty, and last used time should be 0. + WebappDataStorage storage = WebappRegistry.getInstance().getWebappDataStorage("first"); + assertEquals("", storage.getScope()); + assertEquals("", storage.getUrl()); + assertEquals(0, storage.getLastUsedTime()); } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java index 1363c17..c848ff8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
@@ -208,7 +208,7 @@ } } - static class MockTabPersistentStoreObserver implements TabPersistentStoreObserver { + static class MockTabPersistentStoreObserver extends TabPersistentStoreObserver { public final CallbackHelper initializedCallback = new CallbackHelper(); public final CallbackHelper detailsReadCallback = new CallbackHelper(); public final CallbackHelper stateLoadedCallback = new CallbackHelper();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenManagerTest.java index 01aa9621..4e1777bb 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenManagerTest.java
@@ -96,7 +96,7 @@ } private static class TestDataStorageFactory extends WebappDataStorage.Factory { - public Bitmap mSplashImage; + public String mSplashImage; @Override public WebappDataStorage create(final String webappId) { @@ -110,7 +110,7 @@ } @Override - public void updateSplashScreenImage(Bitmap splashScreenImage) { + public void updateSplashScreenImage(String splashScreenImage) { assertNull(mSplashImage); mSplashImage = splashScreenImage; } @@ -280,8 +280,10 @@ // Test that bitmap sizes match expectations. int idealSize = mActivity.getResources().getDimensionPixelSize( R.dimen.webapp_splash_image_size_ideal); - assertEquals(idealSize, dataStorageFactory.mSplashImage.getWidth()); - assertEquals(idealSize, dataStorageFactory.mSplashImage.getHeight()); + Bitmap splashImage = + ShortcutHelper.decodeBitmapFromString(dataStorageFactory.mSplashImage); + assertEquals(idealSize, splashImage.getWidth()); + assertEquals(idealSize, splashImage.getHeight()); } finally { mTestServer.stopAndDestroyServer(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/TestFetchStorageCallback.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/TestFetchStorageCallback.java new file mode 100644 index 0000000..567fb537 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/TestFetchStorageCallback.java
@@ -0,0 +1,25 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.webapps; + +import org.chromium.content.browser.test.util.CallbackHelper; + +/** + * CallbackHelper subclass which implements WebappRegistry.FetchWebappDataStorageCallback for tests. + */ +public class TestFetchStorageCallback + extends CallbackHelper implements WebappRegistry.FetchWebappDataStorageCallback { + protected WebappDataStorage mStorage; + + @Override + public void onWebappDataStorageRetrieved(WebappDataStorage storage) { + mStorage = storage; + notifyCalled(); + } + + public WebappDataStorage getStorage() { + return mStorage; + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTestBase.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTestBase.java index ec1f26a..e63b80f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTestBase.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTestBase.java
@@ -92,16 +92,12 @@ protected void setUp() throws Exception { super.setUp(); - // Register the webapp so when the data storage is opened, the test doesn't crash. There is - // no race condition with the retrieval as AsyncTasks are run sequentially on the background - // thread. - WebappRegistry.registerWebapp( - WEBAPP_ID, new WebappRegistry.FetchWebappDataStorageCallback() { - @Override - public void onWebappDataStorageRetrieved(WebappDataStorage storage) { - storage.updateFromShortcutIntent(createIntent()); - } - }); + // Register the webapp so when the data storage is opened, the test doesn't crash. + WebappRegistry.refreshSharedPrefsForTesting(); + TestFetchStorageCallback callback = new TestFetchStorageCallback(); + WebappRegistry.getInstance().register(WEBAPP_ID, callback); + callback.waitForCallback(0); + callback.getStorage().updateFromShortcutIntent(createIntent()); } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappInfoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappInfoTest.java index 2266711..b484364 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappInfoTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappInfoTest.java
@@ -211,63 +211,19 @@ @SmallTest @Feature({"Webapps", "WebApk"}) public void testIntentDisplayMode() { - { - Intent intent = createIntentWithUrlAndId(); - intent.putExtra(ShortcutHelper.EXTRA_DISPLAY_MODE, WebDisplayMode.MinimalUi); - WebappInfo info = WebappInfo.create(intent); - assertEquals(WebDisplayMode.MinimalUi, info.displayMode()); - } - { - Intent intent = createIntentWithUrlAndId(); - intent.putExtra(WebApkConstants.EXTRA_WEBAPK_DISPLAY_MODE, "fullscreen"); - WebappInfo info = WebappInfo.create(intent); - assertEquals(WebDisplayMode.Fullscreen, info.displayMode()); - } - { - // EXTRA_WEBAPK_DISPLAY_MODE takes precedence over EXTRA_DISPLAY_MODE. - Intent intent = createIntentWithUrlAndId(); - intent.putExtra(WebApkConstants.EXTRA_WEBAPK_DISPLAY_MODE, "fullscreen"); - intent.putExtra(ShortcutHelper.EXTRA_DISPLAY_MODE, WebDisplayMode.MinimalUi); - WebappInfo info = WebappInfo.create(intent); - assertEquals(WebDisplayMode.Fullscreen, info.displayMode()); - } - { - Intent intent = createIntentWithUrlAndId(); - intent.putExtra(WebApkConstants.EXTRA_WEBAPK_DISPLAY_MODE, "invalid"); - WebappInfo info = WebappInfo.create(intent); - assertEquals(WebDisplayMode.Standalone, info.displayMode()); - } + Intent intent = createIntentWithUrlAndId(); + intent.putExtra(ShortcutHelper.EXTRA_DISPLAY_MODE, WebDisplayMode.MinimalUi); + WebappInfo info = WebappInfo.create(intent); + assertEquals(WebDisplayMode.MinimalUi, info.displayMode()); } @SmallTest @Feature({"Webapps", "WebApk"}) public void testIntentOrientation() { - { - Intent intent = createIntentWithUrlAndId(); - intent.putExtra(ShortcutHelper.EXTRA_ORIENTATION, ScreenOrientationValues.LANDSCAPE); - WebappInfo info = WebappInfo.create(intent); - assertEquals(ScreenOrientationValues.LANDSCAPE, info.orientation()); - } - { - Intent intent = createIntentWithUrlAndId(); - intent.putExtra(WebApkConstants.EXTRA_WEBAPK_ORIENTATION, "natural"); - WebappInfo info = WebappInfo.create(intent); - assertEquals(ScreenOrientationValues.NATURAL, info.orientation()); - } - { - // EXTRA_WEBAPK_ORIENTATION takes precedence over EXTRA_ORIENTATION. - Intent intent = createIntentWithUrlAndId(); - intent.putExtra(WebApkConstants.EXTRA_WEBAPK_ORIENTATION, "natural"); - intent.putExtra(ShortcutHelper.EXTRA_ORIENTATION, ScreenOrientationValues.LANDSCAPE); - WebappInfo info = WebappInfo.create(intent); - assertEquals(ScreenOrientationValues.NATURAL, info.orientation()); - } - { - Intent intent = createIntentWithUrlAndId(); - intent.putExtra(WebApkConstants.EXTRA_WEBAPK_ORIENTATION, "invalid"); - WebappInfo info = WebappInfo.create(intent); - assertEquals(ScreenOrientationValues.DEFAULT, info.orientation()); - } + Intent intent = createIntentWithUrlAndId(); + intent.putExtra(ShortcutHelper.EXTRA_ORIENTATION, ScreenOrientationValues.LANDSCAPE); + WebappInfo info = WebappInfo.create(intent); + assertEquals(ScreenOrientationValues.LANDSCAPE, info.orientation()); } @SmallTest
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java index c29dab6..9c5d5b0 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java
@@ -93,11 +93,12 @@ @Override public void setUp() throws Exception { super.setUp(); + WebappRegistry.refreshSharedPrefsForTesting(); // Register the webapps so when the data storage is opened, the test doesn't crash. There is // no race condition with the retrieval as AsyncTasks are run sequentially on the background // thread. - WebappRegistry.registerWebapp( + WebappRegistry.getInstance().register( WEBAPP_1_ID, new WebappRegistry.FetchWebappDataStorageCallback() { @Override public void onWebappDataStorageRetrieved(WebappDataStorage storage) { @@ -105,7 +106,7 @@ WEBAPP_1_ID, WEBAPP_1_URL, WEBAPP_1_TITLE, WEBAPP_ICON, true)); } }); - WebappRegistry.registerWebapp( + WebappRegistry.getInstance().register( WEBAPP_2_ID, new WebappRegistry.FetchWebappDataStorageCallback() { @Override public void onWebappDataStorageRetrieved(WebappDataStorage storage) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenIconTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenIconTest.java index 14c1d72..e10c5aa 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenIconTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenIconTest.java
@@ -34,7 +34,8 @@ @Override protected void setUp() throws Exception { super.setUp(); - WebappDataStorage.open(WEBAPP_ID).updateSplashScreenImageForTests(TEST_SPLASH_ICON); + WebappRegistry.getInstance().getWebappDataStorage(WEBAPP_ID).updateSplashScreenImage( + TEST_SPLASH_ICON); startWebappActivity(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java index dc7f8945e..cf5bbcc47 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java
@@ -33,6 +33,7 @@ * Tests for splash screens. */ public class WebappSplashScreenTest extends WebappActivityTestBase { + private int getHistogramTotalCountFor(String histogram, int buckets) { int count = 0; @@ -236,9 +237,14 @@ Context context = getInstrumentation().getTargetContext(); int thresholdSize = context.getResources().getDimensionPixelSize( R.dimen.webapp_splash_image_size_threshold); - int bitmapSize = thresholdSize + 1; - Bitmap splashBitmap = Bitmap.createBitmap(bitmapSize, bitmapSize, Bitmap.Config.ARGB_8888); - WebappDataStorage.open(WEBAPP_ID).updateSplashScreenImage(splashBitmap); + int size = thresholdSize + 1; + Bitmap splashBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); + String bitmapString = ShortcutHelper.encodeBitmapAsString(splashBitmap); + + TestFetchStorageCallback callback = new TestFetchStorageCallback(); + WebappRegistry.getInstance().register(WEBAPP_ID, callback); + callback.waitForCallback(0); + callback.getStorage().updateSplashScreenImage(bitmapString); startWebappActivity(createIntent()); ViewGroup splashScreen = waitUntilSplashScreenAppears(); @@ -246,8 +252,8 @@ ImageView splashImage = (ImageView) splashScreen.findViewById(R.id.webapp_splash_screen_icon); - assertEquals(bitmapSize, splashImage.getMeasuredWidth()); - assertEquals(bitmapSize, splashImage.getMeasuredHeight()); + assertEquals(size, splashImage.getMeasuredWidth()); + assertEquals(size, splashImage.getMeasuredHeight()); TextView splashText = (TextView) splashScreen.findViewById(R.id.webapp_splash_screen_name); int[] rules = ((RelativeLayout.LayoutParams) splashText.getLayoutParams()).getRules(); @@ -263,10 +269,15 @@ Context context = getInstrumentation().getTargetContext(); int thresholdSize = context.getResources().getDimensionPixelSize( R.dimen.webapp_splash_image_size_threshold); - int bitmapSize = context.getResources().getDimensionPixelSize( + int size = context.getResources().getDimensionPixelSize( R.dimen.webapp_splash_image_size_minimum); - Bitmap splashBitmap = Bitmap.createBitmap(bitmapSize, bitmapSize, Bitmap.Config.ARGB_8888); - WebappDataStorage.open(WEBAPP_ID).updateSplashScreenImage(splashBitmap); + Bitmap splashBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); + String bitmapString = ShortcutHelper.encodeBitmapAsString(splashBitmap); + + TestFetchStorageCallback callback = new TestFetchStorageCallback(); + WebappRegistry.getInstance().register(WEBAPP_ID, callback); + callback.waitForCallback(0); + callback.getStorage().updateSplashScreenImage(bitmapString); startWebappActivity(createIntent()); ViewGroup splashScreen = waitUntilSplashScreenAppears(); @@ -291,10 +302,15 @@ public void testSplashScreenWithoutImageAppears() throws Exception { // Register an image that's too small for the splash screen. Context context = getInstrumentation().getTargetContext(); - int bitmapSize = context.getResources().getDimensionPixelSize( + int size = context.getResources().getDimensionPixelSize( R.dimen.webapp_splash_image_size_minimum) - 1; - Bitmap splashBitmap = Bitmap.createBitmap(bitmapSize, bitmapSize, Bitmap.Config.ARGB_8888); - WebappDataStorage.open(WEBAPP_ID).updateSplashScreenImage(splashBitmap); + Bitmap splashBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); + String bitmapString = ShortcutHelper.encodeBitmapAsString(splashBitmap); + + TestFetchStorageCallback callback = new TestFetchStorageCallback(); + WebappRegistry.getInstance().register(WEBAPP_ID, callback); + callback.waitForCallback(0); + callback.getStorage().updateSplashScreenImage(bitmapString); Intent intent = createIntent(); intent.putExtra(ShortcutHelper.EXTRA_IS_ICON_GENERATED, true);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java index 77b1ed21..a129cdfe 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
@@ -755,6 +755,7 @@ @Test @Feature({"Ntp"}) public void testSigninPromo() { + when(mMockSigninManager.isSignInAllowed()).thenReturn(true); when(mMockSigninManager.isSignedInOnNative()).thenReturn(false); MockNewTabPageManager ntpManager = new MockNewTabPageManager(mSource); NewTabPageAdapter adapter = new NewTabPageAdapter(ntpManager, null, null); @@ -787,6 +788,7 @@ @Test @Feature({"Ntp"}) public void testSigninPromoDismissal() { + when(mMockSigninManager.isSignInAllowed()).thenReturn(true); when(mMockSigninManager.isSignedInOnNative()).thenReturn(false); ChromePreferenceManager.getInstance(RuntimeEnvironment.application) .setNewTabPageSigninPromoDismissed(false);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkMetaDataUtilsTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkMetaDataUtilsTest.java new file mode 100644 index 0000000..ea771d2 --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkMetaDataUtilsTest.java
@@ -0,0 +1,117 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.webapps; + +import android.app.Application; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.os.Bundle; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.Shadows; +import org.robolectric.annotation.Config; +import org.robolectric.res.builder.RobolectricPackageManager; +import org.robolectric.shadows.ShadowApplication; + +import org.chromium.base.ContextUtils; +import org.chromium.blink_public.platform.WebDisplayMode; +import org.chromium.content_public.common.ScreenOrientationValues; +import org.chromium.testing.local.LocalRobolectricTestRunner; +import org.chromium.webapk.lib.common.WebApkConstants; +import org.chromium.webapk.lib.common.WebApkMetaDataKeys; + +/** + * Tests WebApkMetaDataUtils. + */ +@RunWith(LocalRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class WebApkMetaDataUtilsTest { + + private static final String PACKAGE_NAME = "package_name"; + + // Android Manifest meta data for {@link PACKAGE_NAME}. + private static final String START_URL = "https://www.google.com/scope/a_is_for_apple"; + private static final String SCOPE = "https://www.google.com/scope"; + private static final String NAME = "name"; + private static final String SHORT_NAME = "short_name"; + private static final String DISPLAY_MODE = "minimal-ui"; + private static final String ORIENTATION = "portrait"; + private static final String THEME_COLOR = "1L"; + private static final String BACKGROUND_COLOR = "2L"; + + private ShadowApplication mShadowApplication; + private RobolectricPackageManager mPackageManager; + + @Before + public void setUp() { + Application application = RuntimeEnvironment.application; + ContextUtils.initApplicationContextForTests(application); + mShadowApplication = Shadows.shadowOf(application); + mShadowApplication.setPackageName(PACKAGE_NAME); + mPackageManager = (RobolectricPackageManager) application.getPackageManager(); + } + + @Test + public void testSanity() { + Bundle bundle = new Bundle(); + bundle.putString(WebApkMetaDataKeys.SCOPE, SCOPE); + bundle.putString(WebApkMetaDataKeys.NAME, NAME); + bundle.putString(WebApkMetaDataKeys.SHORT_NAME, SHORT_NAME); + bundle.putString(WebApkMetaDataKeys.DISPLAY_MODE, DISPLAY_MODE); + bundle.putString(WebApkMetaDataKeys.ORIENTATION, ORIENTATION); + bundle.putString(WebApkMetaDataKeys.THEME_COLOR, THEME_COLOR); + bundle.putString(WebApkMetaDataKeys.BACKGROUND_COLOR, BACKGROUND_COLOR); + PackageInfo packageInfo = newPackageInfo(PACKAGE_NAME, bundle); + mPackageManager.addPackage(packageInfo); + + WebappInfo webappInfo = + WebApkMetaDataUtils.extractWebappInfoFromWebApk(PACKAGE_NAME, START_URL, 0); + + Assert.assertEquals(WebApkConstants.WEBAPK_ID_PREFIX + PACKAGE_NAME, webappInfo.id()); + Assert.assertEquals(SCOPE, webappInfo.scopeUri().toString()); + Assert.assertEquals(NAME, webappInfo.name()); + Assert.assertEquals(SHORT_NAME, webappInfo.shortName()); + Assert.assertEquals(WebDisplayMode.MinimalUi, webappInfo.displayMode()); + Assert.assertEquals(ScreenOrientationValues.PORTRAIT, webappInfo.orientation()); + Assert.assertTrue(webappInfo.hasValidThemeColor()); + Assert.assertEquals(1L, webappInfo.themeColor()); + Assert.assertTrue(webappInfo.hasValidBackgroundColor()); + Assert.assertEquals(2L, webappInfo.backgroundColor()); + Assert.assertEquals(PACKAGE_NAME, webappInfo.webApkPackageName()); + } + + /** + * Test that WebappInfo are populated with the start URL passed to + * {@link extractWebappInfoFromWebApk()} not the start URL in the WebAPK's meta data. When a + * WebAPK is launched via a deep link from a URL within the WebAPK's scope, the WebAPK should + * open at the URL it was deep linked from not the WebAPK's start URL. + */ + @Test + public void testUseStartUrlOverride() { + String passedInStartUrl = "https://www.google.com/master_override"; + + Bundle bundle = new Bundle(); + bundle.putString(WebApkMetaDataKeys.START_URL, START_URL); + PackageInfo packageInfo = newPackageInfo(PACKAGE_NAME, bundle); + mPackageManager.addPackage(packageInfo); + + WebappInfo webappInfo = + WebApkMetaDataUtils.extractWebappInfoFromWebApk(PACKAGE_NAME, passedInStartUrl, 0); + Assert.assertEquals(passedInStartUrl, webappInfo.uri().toString()); + } + + private static PackageInfo newPackageInfo(String packageName, Bundle metaData) { + ApplicationInfo applicationInfo = new ApplicationInfo(); + applicationInfo.metaData = metaData; + PackageInfo packageInfo = new PackageInfo(); + packageInfo.packageName = packageName; + packageInfo.applicationInfo = applicationInfo; + return packageInfo; + } +}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java index b4a6894..fedead47 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java
@@ -13,19 +13,21 @@ import android.graphics.Bitmap; import android.os.AsyncTask; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowLooper; + import org.chromium.base.ContextUtils; import org.chromium.base.test.util.Feature; import org.chromium.blink_public.platform.WebDisplayMode; import org.chromium.chrome.browser.ShortcutHelper; import org.chromium.testing.local.BackgroundShadowAsyncTask; import org.chromium.testing.local.LocalRobolectricTestRunner; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; -import org.robolectric.shadows.ShadowLooper; import java.util.concurrent.TimeUnit; @@ -75,10 +77,10 @@ public void setUp() throws Exception { ContextUtils.initApplicationContextForTests(RuntimeEnvironment.application); mSharedPreferences = ContextUtils.getApplicationContext().getSharedPreferences( - "webapp_test", Context.MODE_PRIVATE); + WebappDataStorage.SHARED_PREFS_FILE_PREFIX + "test", Context.MODE_PRIVATE); // Set the last_used as if the web app had been registered by WebappRegistry. - mSharedPreferences.edit().putLong("last_used", 0).apply(); + mSharedPreferences.edit().putLong(WebappDataStorage.KEY_LAST_USED, 0).apply(); mCallbackCalled = false; } @@ -111,13 +113,9 @@ @Test @Feature({"Webapp"}) public void testLastUsedRetrieval() throws Exception { - mSharedPreferences.edit().putLong(WebappDataStorage.KEY_LAST_USED, 100L).apply(); - - WebappDataStorage.getLastUsedTime("test", new FetchCallback<Long>(new Long(100L))); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - - assertTrue(mCallbackCalled); + long lastUsed = 100; + mSharedPreferences.edit().putLong(WebappDataStorage.KEY_LAST_USED, lastUsed).apply(); + assertEquals(lastUsed, new WebappDataStorage("test").getLastUsedTime()); } @Test @@ -127,9 +125,9 @@ mSharedPreferences.edit() .putString(WebappDataStorage.KEY_SPLASH_ICON, ShortcutHelper.encodeBitmapAsString(expected)) - .commit(); - WebappDataStorage.open("test") - .getSplashScreenImage(new WebappDataStorage.FetchCallback<Bitmap>() { + .apply(); + WebappDataStorage.open("test").getSplashScreenImage( + new WebappDataStorage.FetchCallback<Bitmap>() { @Override public void onDataRetrieved(Bitmap actual) { mCallbackCalled = true; @@ -149,38 +147,30 @@ @Test @Feature({"Webapp"}) public void testSplashImageUpdate() throws Exception { - final Bitmap expectedImage = createBitmap(); - WebappDataStorage.open("test").updateSplashScreenImage(expectedImage); + Bitmap expectedImage = createBitmap(); + String imageAsString = ShortcutHelper.encodeBitmapAsString(expectedImage); + WebappDataStorage.open("test").updateSplashScreenImage(imageAsString); BackgroundShadowAsyncTask.runBackgroundTasks(); + ShadowLooper.runUiThreadTasks(); - assertEquals(ShortcutHelper.encodeBitmapAsString(expectedImage), + assertEquals(imageAsString, mSharedPreferences.getString(WebappDataStorage.KEY_SPLASH_ICON, null)); } @Test @Feature({"Webapp"}) public void testScopeRetrieval() throws Exception { - final String scope = "http://drive.google.com"; + String scope = "http://drive.google.com"; mSharedPreferences.edit().putString(WebappDataStorage.KEY_SCOPE, scope).apply(); - - WebappDataStorage.getScope("test", new FetchCallback<String>(scope)); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - - assertTrue(mCallbackCalled); + assertEquals(scope, new WebappDataStorage("test").getScope()); } @Test @Feature({"Webapp"}) public void testUrlRetrieval() throws Exception { - final String url = "https://www.google.com"; + String url = "https://www.google.com"; mSharedPreferences.edit().putString(WebappDataStorage.KEY_URL, url).apply(); - - WebappDataStorage.getUrl("test", new FetchCallback<String>(url)); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - - assertTrue(mCallbackCalled); + assertEquals(url, new WebappDataStorage("test").getUrl()); } @Test @@ -191,14 +181,10 @@ // Opening a data storage doesn't count as a launch. WebappDataStorage storage = WebappDataStorage.open("test"); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); assertTrue(!storage.wasLaunchedRecently()); // When the last used time is updated, then it is a launch. storage.updateLastUsedTime(); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); assertTrue(storage.wasLaunchedRecently()); long lastUsedTime = mSharedPreferences.getLong(WebappDataStorage.KEY_LAST_USED, @@ -263,8 +249,6 @@ WebappDataStorage storage = WebappDataStorage.open("test"); storage.updateFromShortcutIntent(shortcutIntent); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); assertEquals(action, mSharedPreferences.getString(WebappDataStorage.KEY_ACTION, null)); assertEquals(url, mSharedPreferences.getString(WebappDataStorage.KEY_URL, null)); @@ -312,8 +296,6 @@ // Update again from the intent and ensure that the data is restored. storage.updateFromShortcutIntent(shortcutIntent); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); assertEquals(action, mSharedPreferences.getString(WebappDataStorage.KEY_ACTION, null)); assertEquals(url, mSharedPreferences.getString(WebappDataStorage.KEY_URL, null));
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java index 7be71cc..53fc6a83 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java
@@ -13,19 +13,21 @@ import android.os.AsyncTask; import android.text.TextUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowLooper; + import org.chromium.base.ContextUtils; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.ShortcutHelper; import org.chromium.chrome.browser.browsing_data.UrlFilters; import org.chromium.testing.local.BackgroundShadowAsyncTask; import org.chromium.testing.local.LocalRobolectricTestRunner; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; -import org.robolectric.shadows.ShadowLooper; import java.util.Arrays; import java.util.Collections; @@ -52,27 +54,6 @@ private SharedPreferences mSharedPreferences; private boolean mCallbackCalled; - private static class FetchCallback implements WebappRegistry.FetchCallback { - boolean mCallbackCalled; - - Set<String> mExpected; - - FetchCallback(Set<String> expected) { - mCallbackCalled = false; - mExpected = expected; - } - - @Override - public void onWebappIdsRetrieved(Set<String> actual) { - mCallbackCalled = true; - assertEquals(mExpected, actual); - } - - boolean getCallbackCalled() { - return mCallbackCalled; - } - } - private static class FetchStorageCallback implements WebappRegistry.FetchWebappDataStorageCallback { Intent mShortcutIntent; @@ -87,48 +68,6 @@ public void onWebappDataStorageRetrieved(WebappDataStorage storage) { mCallbackCalled = true; storage.updateFromShortcutIntent(mShortcutIntent); - storage.updateLastUsedTime(); - } - - boolean getCallbackCalled() { - return mCallbackCalled; - } - } - - private static class FetchStorageByUrlCallback - implements WebappRegistry.FetchWebappDataStorageCallback { - String mUrl; - String mScope; - boolean mCallbackCalled; - - FetchStorageByUrlCallback(String url, String scope) { - mCallbackCalled = false; - mUrl = url; - mScope = scope; - } - - @Override - public void onWebappDataStorageRetrieved(WebappDataStorage storage) { - mCallbackCalled = true; - assertEquals(mUrl, storage.getUrl()); - assertEquals(mScope, storage.getScope()); - } - - boolean getCallbackCalled() { - return mCallbackCalled; - } - } - - private static class CallbackRunner implements Runnable { - boolean mCallbackCalled; - - public CallbackRunner() { - mCallbackCalled = false; - } - - @Override - public void run() { - mCallbackCalled = true; } boolean getCallbackCalled() { @@ -139,6 +78,7 @@ @Before public void setUp() throws Exception { ContextUtils.initApplicationContextForTests(RuntimeEnvironment.application); + WebappRegistry.refreshSharedPrefsForTesting(); mSharedPreferences = ContextUtils.getApplicationContext().getSharedPreferences( REGISTRY_FILE_NAME, Context.MODE_PRIVATE); mSharedPreferences.edit().putLong(KEY_LAST_CLEANUP, INITIAL_TIME).commit(); @@ -151,6 +91,16 @@ mSharedPreferences.edit().clear().apply(); } + private void registerWebapp(String webappId, + WebappRegistry.FetchWebappDataStorageCallback callback) throws Exception { + WebappRegistry.getInstance().register(webappId, callback); + + // Run background tasks to make sure the data is committed. Run UI thread tasks to make sure + // the last used time is updated. + BackgroundShadowAsyncTask.runBackgroundTasks(); + ShadowLooper.runUiThreadTasks(); + } + @Test @Feature({"Webapp"}) public void testBackwardCompatibility() { @@ -162,12 +112,8 @@ @Test @Feature({"Webapp"}) public void testWebappRegistrationAddsToSharedPrefs() throws Exception { - WebappRegistry.registerWebapp("test", null); - - BackgroundShadowAsyncTask.runBackgroundTasks(); - - Set<String> actual = mSharedPreferences.getStringSet( - WebappRegistry.KEY_WEBAPP_SET, Collections.<String>emptySet()); + registerWebapp("test", null); + Set<String> actual = getRegisteredWebapps(); assertEquals(1, actual.size()); assertTrue(actual.contains("test")); } @@ -175,11 +121,9 @@ @Test @Feature({"Webapp"}) public void testWebappRegistrationUpdatesLastUsed() throws Exception { - WebappRegistry.registerWebapp("test", null); + registerWebapp("test", null); - BackgroundShadowAsyncTask.runBackgroundTasks(); long after = System.currentTimeMillis(); - SharedPreferences webAppPrefs = ContextUtils.getApplicationContext().getSharedPreferences( WebappDataStorage.SHARED_PREFS_FILE_PREFIX + "test", Context.MODE_PRIVATE); long actual = webAppPrefs.getLong(WebappDataStorage.KEY_LAST_USED, @@ -191,56 +135,24 @@ @Feature({"Webapp"}) public void testWebappIdsRetrieval() throws Exception { final Set<String> expected = addWebappsToRegistry("first", "second"); - - FetchCallback callback = new FetchCallback(expected); - WebappRegistry.getRegisteredWebappIds(callback); - - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - - assertTrue(callback.getCallbackCalled()); + assertEquals(expected, WebappRegistry.getRegisteredWebappIdsForTesting()); } @Test @Feature({"Webapp"}) public void testWebappIdsRetrievalRegisterRetrival() throws Exception { final Set<String> expected = addWebappsToRegistry("first"); + assertEquals(expected, WebappRegistry.getRegisteredWebappIdsForTesting()); - FetchCallback callback = new FetchCallback(expected); - WebappRegistry.getRegisteredWebappIds(callback); - - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - - assertTrue(callback.getCallbackCalled()); - - WebappRegistry.registerWebapp("second", null); - - BackgroundShadowAsyncTask.runBackgroundTasks(); + // Force a re-read of the preferences from disk. Add a new web app via the registry. + WebappRegistry.refreshSharedPrefsForTesting(); + registerWebapp("second", null); // A copy of the expected set needs to be made as the SharedPreferences is using the copy - // that was paassed to it. + // that was passed to it. final Set<String> secondExpected = new HashSet<>(expected); secondExpected.add("second"); - - callback = new FetchCallback(secondExpected); - WebappRegistry.getRegisteredWebappIds(callback); - - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - - assertTrue(callback.getCallbackCalled()); - } - - @Test - @Feature({"Webapp"}) - public void testUnregisterRunsCallback() throws Exception { - CallbackRunner callback = new CallbackRunner(); - WebappRegistry.unregisterWebappsForUrls(new UrlFilters.AllUrls(), callback); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - - assertTrue(callback.getCallbackCalled()); + assertEquals(secondExpected, WebappRegistry.getRegisteredWebappIdsForTesting()); } @Test @@ -252,20 +164,14 @@ apps.put("webapp3", "https://www.chrome.com"); for (Map.Entry<String, String> app : apps.entrySet()) { - WebappRegistry.registerWebapp( + registerWebapp( app.getKey(), new FetchStorageCallback(createShortcutIntent(app.getValue()))); } - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); // Partial deletion. - CallbackRunner callback = new CallbackRunner(); - WebappRegistry.unregisterWebappsForUrls( - new UrlFilters.OneUrl("http://example.com/index.html"), callback); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); + WebappRegistry.getInstance().unregisterWebappsForUrlsImpl( + new UrlFilters.OneUrl("http://example.com/index.html")); - assertTrue(callback.getCallbackCalled()); Set<String> registeredWebapps = getRegisteredWebapps(); assertEquals(2, registeredWebapps.size()); for (String appName : apps.keySet()) { @@ -274,12 +180,7 @@ } // Full deletion. - callback = new CallbackRunner(); - WebappRegistry.unregisterWebappsForUrls(new UrlFilters.AllUrls(), callback); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - - assertTrue(callback.getCallbackCalled()); + WebappRegistry.getInstance().unregisterWebappsForUrlsImpl(new UrlFilters.AllUrls()); assertTrue(getRegisteredWebapps().isEmpty()); } @@ -292,11 +193,9 @@ apps.put("webapp3", "https://www.chrome.com"); for (Map.Entry<String, String> app : apps.entrySet()) { - WebappRegistry.registerWebapp( + registerWebapp( app.getKey(), new FetchStorageCallback(createShortcutIntent(app.getValue()))); } - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); for (String appName : apps.keySet()) { SharedPreferences webAppPrefs = @@ -307,10 +206,9 @@ } // Partial deletion. - WebappRegistry.unregisterWebappsForUrls( - new UrlFilters.OneUrl("http://example.com/index.html"), null); + WebappRegistry.getInstance().unregisterWebappsForUrlsImpl( + new UrlFilters.OneUrl("http://example.com/index.html")); - BackgroundShadowAsyncTask.runBackgroundTasks(); for (String appName : apps.keySet()) { SharedPreferences webAppPrefs = ContextUtils.getApplicationContext().getSharedPreferences( @@ -320,8 +218,7 @@ } // Full deletion. - WebappRegistry.unregisterWebappsForUrls(new UrlFilters.AllUrls(), null); - BackgroundShadowAsyncTask.runBackgroundTasks(); + WebappRegistry.getInstance().unregisterWebappsForUrlsImpl(new UrlFilters.AllUrls()); for (String appName : apps.keySet()) { SharedPreferences webAppPrefs = ContextUtils.getApplicationContext().getSharedPreferences( @@ -342,11 +239,11 @@ WebappDataStorage.SHARED_PREFS_FILE_PREFIX + "oldWebapp", Context.MODE_PRIVATE); webAppPrefs.edit().putLong(WebappDataStorage.KEY_LAST_USED, Long.MIN_VALUE).apply(); - WebappRegistry.unregisterOldWebapps(currentTime); - BackgroundShadowAsyncTask.runBackgroundTasks(); + // Force a re-read of the preferences from disk. + WebappRegistry.refreshSharedPrefsForTesting(); + WebappRegistry.getInstance().unregisterOldWebapps(currentTime); - Set<String> actual = mSharedPreferences.getStringSet( - WebappRegistry.KEY_WEBAPP_SET, Collections.<String>emptySet()); + Set<String> actual = getRegisteredWebapps(); assertEquals(new HashSet<>(Arrays.asList("oldWebapp")), actual); long actualLastUsed = webAppPrefs.getLong(WebappDataStorage.KEY_LAST_USED, @@ -371,14 +268,15 @@ long lastUsed = currentTime - WebappRegistry.WEBAPP_UNOPENED_CLEANUP_DURATION + 1; webAppPrefs.edit().putLong(WebappDataStorage.KEY_LAST_USED, lastUsed).apply(); + // Force a re-read of the preferences from disk. + WebappRegistry.refreshSharedPrefsForTesting(); + // Because the time is just inside the window, there should be a cleanup but the web app // should not be deleted as it was used recently. The last cleanup time should also be // set to the current time. - WebappRegistry.unregisterOldWebapps(currentTime); - BackgroundShadowAsyncTask.runBackgroundTasks(); + WebappRegistry.getInstance().unregisterOldWebapps(currentTime); - Set<String> actual = mSharedPreferences.getStringSet( - WebappRegistry.KEY_WEBAPP_SET, Collections.<String>emptySet()); + Set<String> actual = getRegisteredWebapps(); assertEquals(new HashSet<>(Arrays.asList("recentWebapp")), actual); long actualLastUsed = webAppPrefs.getLong(WebappDataStorage.KEY_LAST_USED, @@ -402,13 +300,14 @@ long lastUsed = currentTime - WebappRegistry.WEBAPP_UNOPENED_CLEANUP_DURATION; webAppPrefs.edit().putLong(WebappDataStorage.KEY_LAST_USED, lastUsed).apply(); + // Force a re-read of the preferences from disk. + WebappRegistry.refreshSharedPrefsForTesting(); + // Because the time is just inside the window, there should be a cleanup of old web apps and // the last cleaned up time should be set to the current time. - WebappRegistry.unregisterOldWebapps(currentTime); - BackgroundShadowAsyncTask.runBackgroundTasks(); + WebappRegistry.getInstance().unregisterOldWebapps(currentTime); - Set<String> actual = mSharedPreferences.getStringSet( - WebappRegistry.KEY_WEBAPP_SET, Collections.<String>emptySet()); + Set<String> actual = getRegisteredWebapps(); assertTrue(actual.isEmpty()); long actualLastUsed = webAppPrefs.getLong(WebappDataStorage.KEY_LAST_USED, @@ -429,21 +328,16 @@ FetchStorageCallback storageCallback1 = new FetchStorageCallback( createWebApkIntent(webappId1, webApkPackage1)); - WebappRegistry.registerWebapp(webappId1, storageCallback1); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); + registerWebapp(webappId1, storageCallback1); assertTrue(storageCallback1.getCallbackCalled()); FetchStorageCallback storageCallback2 = new FetchStorageCallback( createWebApkIntent(webappId1, webApkPackage2)); - WebappRegistry.registerWebapp(webappId2, storageCallback2); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); + registerWebapp(webappId2, storageCallback2); assertTrue(storageCallback2.getCallbackCalled()); // Verify that both WebAPKs are registered. - Set<String> actual = mSharedPreferences.getStringSet( - WebappRegistry.KEY_WEBAPP_SET, Collections.<String>emptySet()); + Set<String> actual = getRegisteredWebapps(); assertEquals(2, actual.size()); assertTrue(actual.contains(webappId1)); assertTrue(actual.contains(webappId2)); @@ -453,13 +347,9 @@ // Because the time is just inside the window, there should be a cleanup of // uninstalled WebAPKs and the last cleaned up time should be set to the // current time. - WebappRegistry.unregisterOldWebapps(currentTime); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); + WebappRegistry.getInstance().unregisterOldWebapps(currentTime); - actual = mSharedPreferences.getStringSet( - WebappRegistry.KEY_WEBAPP_SET, Collections.<String>emptySet()); - assertTrue(actual.isEmpty()); + assertTrue(getRegisteredWebapps().isEmpty()); long lastCleanup = mSharedPreferences.getLong( WebappRegistry.KEY_LAST_CLEANUP, -1); @@ -476,21 +366,16 @@ FetchStorageCallback storageCallback = new FetchStorageCallback( createWebApkIntent(webappId, webApkPackage)); - WebappRegistry.registerWebapp(webappId, storageCallback); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); + registerWebapp(webappId, storageCallback); assertTrue(storageCallback.getCallbackCalled()); FetchStorageCallback storageCallback2 = new FetchStorageCallback( createWebApkIntent(uninstalledWebappId, uninstalledWebApkPackage)); - WebappRegistry.registerWebapp(uninstalledWebappId, storageCallback2); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); + registerWebapp(uninstalledWebappId, storageCallback2); assertTrue(storageCallback2.getCallbackCalled()); // Verify that both WebAPKs are registered. - Set<String> actual = mSharedPreferences.getStringSet( - WebappRegistry.KEY_WEBAPP_SET, Collections.<String>emptySet()); + Set<String> actual = getRegisteredWebapps(); assertEquals(2, actual.size()); assertTrue(actual.contains(webappId)); assertTrue(actual.contains(uninstalledWebappId)); @@ -502,12 +387,9 @@ // Because the time is just inside the window, there should be a cleanup of // uninstalled WebAPKs and the last cleaned up time should be set to the // current time. - WebappRegistry.unregisterOldWebapps(currentTime); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); + WebappRegistry.getInstance().unregisterOldWebapps(currentTime); - actual = mSharedPreferences.getStringSet( - WebappRegistry.KEY_WEBAPP_SET, Collections.<String>emptySet()); + actual = getRegisteredWebapps(); assertEquals(1, actual.size()); assertTrue(actual.contains(webappId)); @@ -518,17 +400,6 @@ @Test @Feature({"Webapp"}) - public void testClearWebappHistoryRunsCallback() throws Exception { - CallbackRunner callback = new CallbackRunner(); - WebappRegistry.clearWebappHistoryForUrls(new UrlFilters.AllUrls(), callback); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - - assertTrue(callback.getCallbackCalled()); - } - - @Test - @Feature({"Webapp"}) public void testClearWebappHistory() throws Exception { final String webapp1Url = "https://www.google.com"; final String webapp2Url = "https://drive.google.com"; @@ -536,15 +407,11 @@ Intent shortcutIntent2 = createShortcutIntent(webapp2Url); FetchStorageCallback storageCallback1 = new FetchStorageCallback(shortcutIntent1); - WebappRegistry.registerWebapp("webapp1", storageCallback1); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); + registerWebapp("webapp1", storageCallback1); assertTrue(storageCallback1.getCallbackCalled()); FetchStorageCallback storageCallback2 = new FetchStorageCallback(shortcutIntent2); - WebappRegistry.registerWebapp("webapp2", storageCallback2); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); + registerWebapp("webapp2", storageCallback2); assertTrue(storageCallback2.getCallbackCalled()); SharedPreferences webapp1Prefs = ContextUtils.getApplicationContext().getSharedPreferences( @@ -560,14 +427,10 @@ assertTrue(webapp2OriginalLastUsed != WebappDataStorage.LAST_USED_UNSET); // Clear data for |webapp1Url|. - CallbackRunner callback = new CallbackRunner(); - WebappRegistry.clearWebappHistoryForUrls(new UrlFilters.OneUrl(webapp1Url), callback); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - assertTrue(callback.getCallbackCalled()); + WebappRegistry.getInstance().clearWebappHistoryForUrlsImpl( + new UrlFilters.OneUrl(webapp1Url)); - Set<String> actual = mSharedPreferences.getStringSet( - WebappRegistry.KEY_WEBAPP_SET, Collections.<String>emptySet()); + Set<String> actual = getRegisteredWebapps(); assertEquals(2, actual.size()); assertTrue(actual.contains("webapp1")); assertTrue(actual.contains("webapp2")); @@ -597,11 +460,7 @@ assertEquals(webapp2Url, actualUrl); // Clear data for all urls. - callback = new CallbackRunner(); - WebappRegistry.clearWebappHistoryForUrls(new UrlFilters.AllUrls(), callback); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - assertTrue(callback.getCallbackCalled()); + WebappRegistry.getInstance().clearWebappHistoryForUrlsImpl(new UrlFilters.AllUrls()); // Verify that the last used time for both web apps is WebappDataStorage.LAST_USED_UNSET. actualLastUsed = webapp1Prefs.getLong( @@ -629,23 +488,14 @@ @Test @Feature({"Webapp"}) public void testGetAfterClearWebappHistory() throws Exception { - WebappRegistry.registerWebapp("webapp", null); - BackgroundShadowAsyncTask.runBackgroundTasks(); + registerWebapp("webapp", null); SharedPreferences webappPrefs = ContextUtils.getApplicationContext().getSharedPreferences( WebappDataStorage.SHARED_PREFS_FILE_PREFIX + "webapp", Context.MODE_PRIVATE); - CallbackRunner callback = new CallbackRunner(); - WebappRegistry.clearWebappHistoryForUrls(new UrlFilters.AllUrls(), callback); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - assertTrue(callback.getCallbackCalled()); + WebappRegistry.getInstance().clearWebappHistoryForUrlsImpl(new UrlFilters.AllUrls()); - // Open the webapp up to set the last used time. - FetchStorageCallback storageCallback = new FetchStorageCallback(null); - WebappRegistry.getWebappDataStorage("webapp", storageCallback); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - assertTrue(storageCallback.getCallbackCalled()); + // Open the webapp up and set the last used time. + WebappRegistry.getInstance().getWebappDataStorage("webapp").updateLastUsedTime(); // Verify that the last used time is valid. long actualLastUsed = webappPrefs.getLong( @@ -660,9 +510,7 @@ final String webappUrl = "http://www.google.com"; final String webappScope = "http://www.google.com/"; final Intent shortcutIntent = createShortcutIntent(webappUrl); - WebappRegistry.registerWebapp("webapp", new FetchStorageCallback(shortcutIntent)); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); + registerWebapp("webapp", new FetchStorageCallback(shortcutIntent)); SharedPreferences webappPrefs = ContextUtils.getApplicationContext().getSharedPreferences( WebappDataStorage.SHARED_PREFS_FILE_PREFIX + "webapp", Context.MODE_PRIVATE); @@ -675,14 +523,11 @@ WebappDataStorage.KEY_SCOPE, WebappDataStorage.URL_INVALID); assertEquals(webappScope, actualScope); - WebappRegistry.clearWebappHistoryForUrls(new UrlFilters.AllUrls(), new CallbackRunner()); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); + WebappRegistry.getInstance().clearWebappHistoryForUrlsImpl(new UrlFilters.AllUrls()); // Update the webapp from the intent again. - WebappRegistry.getWebappDataStorage("webapp", new FetchStorageCallback(shortcutIntent)); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); + WebappDataStorage storage = WebappRegistry.getInstance().getWebappDataStorage("webapp"); + storage.updateFromShortcutIntent(shortcutIntent); // Verify that the URL and scope match the original in the intent. actualUrl = webappPrefs.getString(WebappDataStorage.KEY_URL, WebappDataStorage.URL_INVALID); @@ -718,72 +563,45 @@ Intent shortcutIntent4 = createShortcutIntent(webapp4Url); // Register the four web apps. - WebappRegistry.registerWebapp("webapp1", new FetchStorageCallback(shortcutIntent1)); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - - WebappRegistry.registerWebapp("webapp2", new FetchStorageCallback(shortcutIntent2)); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - - WebappRegistry.registerWebapp("webapp3", new FetchStorageCallback(shortcutIntent3)); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - - WebappRegistry.registerWebapp("webapp4", new FetchStorageCallback(shortcutIntent4)); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); + registerWebapp("webapp1", new FetchStorageCallback(shortcutIntent1)); + registerWebapp("webapp2", new FetchStorageCallback(shortcutIntent2)); + registerWebapp("webapp3", new FetchStorageCallback(shortcutIntent3)); + registerWebapp("webapp4", new FetchStorageCallback(shortcutIntent4)); // test1Url should return webapp1. - FetchStorageByUrlCallback callback = new FetchStorageByUrlCallback(webapp1Url, webapp1Url); - WebappRegistry.getWebappDataStorageForUrl(test1Url, callback); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - assertTrue(callback.getCallbackCalled()); + WebappDataStorage storage1 = + WebappRegistry.getInstance().getWebappDataStorageForUrl(test1Url); + assertEquals(webapp1Url, storage1.getUrl()); + assertEquals(webapp1Url, storage1.getScope()); // test2Url should return webapp3. - callback = new FetchStorageByUrlCallback(webapp3Url, webapp3Scope); - WebappRegistry.getWebappDataStorageForUrl(test2Url, callback); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - assertTrue(callback.getCallbackCalled()); + WebappDataStorage storage2 = + WebappRegistry.getInstance().getWebappDataStorageForUrl(test2Url); + assertEquals(webapp3Url, storage2.getUrl()); + assertEquals(webapp3Scope, storage2.getScope()); // test3Url should return webapp4. - callback = new FetchStorageByUrlCallback(webapp4Url, webapp4Scope); - WebappRegistry.getWebappDataStorageForUrl(test3Url, callback); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - assertTrue(callback.getCallbackCalled()); + WebappDataStorage storage3 = + WebappRegistry.getInstance().getWebappDataStorageForUrl(test3Url); + assertEquals(webapp4Url, storage3.getUrl()); + assertEquals(webapp4Scope, storage3.getScope()); // test4Url should return webapp4. - callback = new FetchStorageByUrlCallback(webapp4Url, webapp4Scope); - WebappRegistry.getWebappDataStorageForUrl(test4Url, callback); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - assertTrue(callback.getCallbackCalled()); + WebappDataStorage storage4 = + WebappRegistry.getInstance().getWebappDataStorageForUrl(test4Url); + assertEquals(webapp4Url, storage4.getUrl()); + assertEquals(webapp4Scope, storage4.getScope()); // test5Url should return webapp2. - callback = new FetchStorageByUrlCallback(webapp2Url, webapp2Url); - WebappRegistry.getWebappDataStorageForUrl(test5Url, callback); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - assertTrue(callback.getCallbackCalled()); + WebappDataStorage storage5 = + WebappRegistry.getInstance().getWebappDataStorageForUrl(test5Url); + assertEquals(webapp2Url, storage5.getUrl()); + assertEquals(webapp2Url, storage5.getScope()); // test6Url doesn't correspond to a web app, so the storage returned is null. - // This must use a member variable; local variables must be final or effectively final to be - // accessible inside an inner class. - mCallbackCalled = false; - WebappRegistry.getWebappDataStorageForUrl( - test6Url, new WebappRegistry.FetchWebappDataStorageCallback() { - @Override - public void onWebappDataStorageRetrieved(WebappDataStorage storage) { - assertEquals(null, storage); - mCallbackCalled = true; - } - }); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - assertTrue(mCallbackCalled); + WebappDataStorage storage6 = + WebappRegistry.getInstance().getWebappDataStorageForUrl(test6Url); + assertEquals(null, storage6); } private Set<String> addWebappsToRegistry(String... webapps) {
diff --git a/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkConstants.java b/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkConstants.java index 21f2394..53c2cb79 100644 --- a/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkConstants.java +++ b/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkConstants.java
@@ -13,28 +13,11 @@ // WebAPK id prefix. The id is used for storing WebAPK data in Chrome's SharedPreferences. public static final String WEBAPK_ID_PREFIX = "webapk:"; - // Used for sending Android Manifest properties to WebappLauncherActivity. - public static final String EXTRA_WEBAPK_DISPLAY_MODE = - "org.chromium.webapk.lib.common.webapk_display_mode"; - public static final String EXTRA_WEBAPK_ORIENTATION = - "org.chromium.webapk.lib.common.webapk_orientation"; - // These EXTRA_* values must stay in sync with // {@link org.chromium.chrome.browser.ShortcutHelper}. public static final String EXTRA_ID = "org.chromium.chrome.browser.webapp_id"; - public static final String EXTRA_ICON = "org.chromium.chrome.browser.webapp_icon"; - public static final String EXTRA_SHORT_NAME = "org.chromium.chrome.browser.webapp_short_name"; - public static final String EXTRA_NAME = "org.chromium.chrome.browser.webapp_name"; public static final String EXTRA_URL = "org.chromium.chrome.browser.webapp_url"; - public static final String EXTRA_SCOPE = "org.chromium.chrome.browser.webapp_scope"; public static final String EXTRA_SOURCE = "org.chromium.chrome.browser.webapp_source"; - public static final String EXTRA_THEME_COLOR = "org.chromium.chrome.browser.theme_color"; - public static final String EXTRA_BACKGROUND_COLOR = - "org.chromium.chrome.browser.background_color"; - public static final String EXTRA_IS_ICON_GENERATED = - "org.chromium.chrome.browser.is_icon_generated"; public static final String EXTRA_WEBAPK_PACKAGE_NAME = "org.chromium.chrome.browser.webapk_package_name"; - public static final String EXTRA_WEB_MANIFEST_URL = - "org.chromium.chrome.browser.web_manifest_url"; }
diff --git a/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkMetaDataKeys.java b/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkMetaDataKeys.java index 3383d64..7e0d3f2 100644 --- a/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkMetaDataKeys.java +++ b/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkMetaDataKeys.java
@@ -12,11 +12,13 @@ public static final String RUNTIME_HOST = "org.chromium.webapk.shell_apk.runtimeHost"; public static final String START_URL = "org.chromium.webapk.shell_apk.startUrl"; public static final String NAME = "org.chromium.webapk.shell_apk.name"; + public static final String SHORT_NAME = "org.chromium.webapk.shell_apk.shortName"; public static final String SCOPE = "org.chromium.webapk.shell_apk.scope"; public static final String DISPLAY_MODE = "org.chromium.webapk.shell_apk.displayMode"; public static final String ORIENTATION = "org.chromium.webapk.shell_apk.orientation"; public static final String THEME_COLOR = "org.chromium.webapk.shell_apk.themeColor"; public static final String BACKGROUND_COLOR = "org.chromium.webapk.shell_apk.backgroundColor"; + public static final String ICON_ID = "org.chromium.webapk.shell_apk.iconId"; public static final String ICON_URL = "org.chromium.webapk.shell_apk.iconUrl"; public static final String ICON_MURMUR2_HASH = "org.chromium.webapk.shell_apk.iconMurmur2Hash"; public static final String WEB_MANIFEST_URL = "org.chromium.webapk.shell_apk.webManifestUrl";
diff --git a/chrome/android/webapk/libs/runtime_library/BUILD.gn b/chrome/android/webapk/libs/runtime_library/BUILD.gn index 218762a..77fa40f 100644 --- a/chrome/android/webapk/libs/runtime_library/BUILD.gn +++ b/chrome/android/webapk/libs/runtime_library/BUILD.gn
@@ -31,13 +31,8 @@ # library because the dx tool expects files ending in .dex.jar android_library("runtime_library_for_assets_java") { dex_path = "$target_gen_dir/$runtime_library_dex_asset_name" - java_files = [ - "src/org/chromium/webapk/lib/runtime_library/HostBrowserLauncher.java", - "src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java", - ] - deps = [ - "//chrome/android/webapk/libs/common:common_java", - ] + java_files = + [ "src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java" ] srcjar_deps = [ ":webapk_service_aidl" ] }
diff --git a/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/HostBrowserLauncher.java b/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/HostBrowserLauncher.java deleted file mode 100644 index eeec4fa2..0000000 --- a/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/HostBrowserLauncher.java +++ /dev/null
@@ -1,146 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.webapk.lib.runtime_library; - -import android.content.ActivityNotFoundException; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.os.Bundle; -import android.text.TextUtils; -import android.util.Base64; -import android.util.Log; - -import org.chromium.webapk.lib.common.WebApkConstants; -import org.chromium.webapk.lib.common.WebApkMetaDataKeys; - -import java.io.ByteArrayOutputStream; - -/** - * Launches Chrome in WebAPK mode. - */ -public class HostBrowserLauncher { - - // This value is equal to kInvalidOrMissingColor in the C++ content::Manifest struct. - private static final long MANIFEST_COLOR_INVALID_OR_MISSING = ((long) Integer.MAX_VALUE) + 1; - - /** - * Key for passing app icon id in Bundle to {@link #launch()}. - */ - private static final String KEY_APP_ICON_ID = "app_icon_id"; - - private static final String TAG = "cr_HostBrowserLauncher"; - - /** - * Launches Chrome in WebAPK mode. - * @param context Application context. - * @param intent Intent used to launch WebAPK. - * @param bundle Contains extra parameters. - */ - public void launch(Context context, Intent intent, Bundle bundle) { - int appIconId = bundle.getInt(KEY_APP_ICON_ID); - - String packageName = context.getPackageName(); - ApplicationInfo appInfo; - try { - appInfo = context.getPackageManager().getApplicationInfo( - packageName, PackageManager.GET_META_DATA); - } catch (NameNotFoundException e) { - return; - } - - Bundle metaBundle = appInfo.metaData; - String url = metaBundle.getString(WebApkMetaDataKeys.START_URL); - - String overrideUrl = intent.getDataString(); - // TODO(pkotwicz): Use same logic as {@code IntentHandler#shouldIgnoreIntent()} - if (overrideUrl != null && overrideUrl.startsWith("https:")) { - url = overrideUrl; - } - String scope = metaBundle.getString(WebApkMetaDataKeys.SCOPE); - int source = intent.getIntExtra(WebApkConstants.EXTRA_SOURCE, 0); - - String webappId = WebApkConstants.WEBAPK_ID_PREFIX + packageName; - String runtimeHost = metaBundle.getString(WebApkMetaDataKeys.RUNTIME_HOST); - String shortName = (String) context.getPackageManager().getApplicationLabel(appInfo); - // TODO(hanxi): find a neat solution to avoid encode/decode each time launch the - // activity. - Bitmap icon = BitmapFactory.decodeResource(context.getResources(), appIconId); - String encodedIcon = encodeBitmapAsString(icon); - String name = metaBundle.getString(WebApkMetaDataKeys.NAME); - String displayMode = metaBundle.getString(WebApkMetaDataKeys.DISPLAY_MODE); - String orientation = metaBundle.getString(WebApkMetaDataKeys.ORIENTATION); - long themeColor = getColorFromBundle(metaBundle, WebApkMetaDataKeys.THEME_COLOR); - long backgroundColor = getColorFromBundle(metaBundle, WebApkMetaDataKeys.BACKGROUND_COLOR); - boolean isIconGenerated = - TextUtils.isEmpty(metaBundle.getString(WebApkMetaDataKeys.ICON_URL)); - Log.v(TAG, "Url of the WebAPK: " + url); - Log.v(TAG, "WebappId of the WebAPK: " + webappId); - Log.v(TAG, "Name of the WebAPK:" + name); - Log.v(TAG, "Package name of the WebAPK:" + packageName); - - Intent newIntent = new Intent(); - newIntent.setComponent(new ComponentName( - runtimeHost, "org.chromium.chrome.browser.webapps.WebappLauncherActivity")); - - // Chrome expects the ShortcutHelper.EXTRA_DISPLAY_MODE and - // ShortcutHelper.EXTRA_ORIENTATION extras to be enum values. We send string extras for - // the display mode and orientation so have to use different keys. - newIntent.putExtra(WebApkConstants.EXTRA_ID, webappId) - .putExtra(WebApkConstants.EXTRA_SHORT_NAME, shortName) - .putExtra(WebApkConstants.EXTRA_NAME, name) - .putExtra(WebApkConstants.EXTRA_URL, url) - .putExtra(WebApkConstants.EXTRA_SCOPE, scope) - .putExtra(WebApkConstants.EXTRA_ICON, encodedIcon) - .putExtra(WebApkConstants.EXTRA_SOURCE, source) - .putExtra(WebApkConstants.EXTRA_THEME_COLOR, themeColor) - .putExtra(WebApkConstants.EXTRA_BACKGROUND_COLOR, backgroundColor) - .putExtra(WebApkConstants.EXTRA_IS_ICON_GENERATED, isIconGenerated) - .putExtra(WebApkConstants.EXTRA_WEBAPK_PACKAGE_NAME, packageName) - .putExtra(WebApkConstants.EXTRA_WEBAPK_DISPLAY_MODE, displayMode) - .putExtra(WebApkConstants.EXTRA_WEBAPK_ORIENTATION, orientation); - - try { - context.startActivity(newIntent); - } catch (ActivityNotFoundException e) { - e.printStackTrace(); - } - } - - /** - * Compresses a bitmap into a PNG and converts into a Base64 encoded string. - * The encoded string can be decoded using {@link decodeBitmapFromString(String)}. - * @param bitmap The Bitmap to compress and encode. - * @return the String encoding the Bitmap. - */ - private static String encodeBitmapAsString(Bitmap bitmap) { - if (bitmap == null) return ""; - ByteArrayOutputStream output = new ByteArrayOutputStream(); - bitmap.compress(Bitmap.CompressFormat.PNG, 100, output); - return Base64.encodeToString(output.toByteArray(), Base64.DEFAULT); - } - - /** - * Gets the long value of a color from a Bundle. The long should be terminated with 'L'. This - * function is more reliable than Bundle#getLong() which returns 0 if the value is below - * Float.MAX_VALUE. Returns {@link MANIFEST_COLOR_INVALID_OR_MISSING} when the color is missing. - */ - private static long getColorFromBundle(Bundle bundle, String key) { - String value = bundle.getString(key); - if (value == null || !value.endsWith("L")) { - return MANIFEST_COLOR_INVALID_OR_MISSING; - } - try { - return Long.parseLong(value.substring(0, value.length() - 1)); - } catch (NumberFormatException e) { - } - return 0; - } -}
diff --git a/chrome/android/webapk/shell_apk/AndroidManifest.xml b/chrome/android/webapk/shell_apk/AndroidManifest.xml index 7f5e8627..7018924 100644 --- a/chrome/android/webapk/shell_apk/AndroidManifest.xml +++ b/chrome/android/webapk/shell_apk/AndroidManifest.xml
@@ -40,11 +40,13 @@ <meta-data android:name="org.chromium.webapk.shell_apk.runtimeHost" android:value="{{ runtime_host }}" /> <meta-data android:name="org.chromium.webapk.shell_apk.startUrl" android:value="{{ start_url }}" /> <meta-data android:name="org.chromium.webapk.shell_apk.name" android:value="{{ name }}" /> + <meta-data android:name="org.chromium.webapk.shell_apk.shortName" android:value="{{ short_name }}" /> <meta-data android:name="org.chromium.webapk.shell_apk.scope" android:value="{{ scope_url }}" /> <meta-data android:name="org.chromium.webapk.shell_apk.displayMode" android:value="{{ display_mode }}" /> <meta-data android:name="org.chromium.webapk.shell_apk.orientation" android:value="{{ orientation }}" /> <meta-data android:name="org.chromium.webapk.shell_apk.themeColor" android:value="{{ theme_color }}" /> <meta-data android:name="org.chromium.webapk.shell_apk.backgroundColor" android:value="{{ background_color }}" /> + <meta-data android:name="org.chromium.webapk.shell_apk.iconId" android:resource="@mipmap/app_icon" /> <meta-data android:name="org.chromium.webapk.shell_apk.iconUrl" android:value="{{ icon_url }}" /> <meta-data android:name="org.chromium.webapk.shell_apk.iconMurmur2Hash" android:value="{{ icon_murmur2_hash }}" /> <meta-data android:name="org.chromium.webapk.shell_apk.webManifestUrl" android:value="{{ web_manifest_url }}" />
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/MainActivity.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/MainActivity.java index a99304e..7555141 100644 --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/MainActivity.java +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/MainActivity.java
@@ -6,7 +6,6 @@ import android.app.Activity; import android.content.ActivityNotFoundException; -import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; @@ -18,7 +17,6 @@ import org.chromium.webapk.lib.common.WebApkConstants; import org.chromium.webapk.lib.common.WebApkMetaDataKeys; -import java.lang.reflect.Method; import java.net.URISyntaxException; /** @@ -33,6 +31,11 @@ private static final String HOST_BROWSER_LAUNCHER_CLASS_NAME = "org.chromium.webapk.lib.runtime_library.HostBrowserLauncher"; + // Action for launching {@link WebappLauncherActivity}. Must stay in sync with + // {@link WebappLauncherActivity#ACTION_START_WEBAPP}. + public static final String ACTION_START_WEBAPK = + "com.google.android.apps.chrome.webapps.WebappManager.ACTION_START_WEBAPP"; + // Must stay in sync with // {@link org.chromium.chrome.browser.ShortcutHelper#REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB}. private static final String REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB = @@ -64,13 +67,13 @@ * Launches WebAPK. */ private void launch() { - if (launchHostBrowserInWebApkMode()) { - return; - } String startUrl = getStartUrl(); if (startUrl == null) { return; } + if (launchHostBrowserInWebApkMode(startUrl)) { + return; + } if (launchBrowser(startUrl)) { return; } @@ -81,25 +84,25 @@ * Launches host browser in WebAPK mode. * @return True if successful. */ - private boolean launchHostBrowserInWebApkMode() { - ClassLoader webApkClassLoader = HostBrowserClassLoader.getClassLoaderInstance( - this, HOST_BROWSER_LAUNCHER_CLASS_NAME); - if (webApkClassLoader == null) { - Log.w(TAG, "Unable to create ClassLoader."); - return false; - } + private boolean launchHostBrowserInWebApkMode(String startUrl) { + Log.v(TAG, "Url of the WebAPK: " + startUrl); + String packageName = getPackageName(); + Log.v(TAG, "Package name of the WebAPK:" + packageName); + + String runtimeHost = WebApkUtils.getHostBrowserPackageName(this); + int source = getIntent().getIntExtra(WebApkConstants.EXTRA_SOURCE, 0); + Intent intent = new Intent(); + intent.setAction(ACTION_START_WEBAPK); + intent.setPackage(runtimeHost); + intent.putExtra(WebApkConstants.EXTRA_ID, WebApkConstants.WEBAPK_ID_PREFIX + packageName) + .putExtra(WebApkConstants.EXTRA_URL, startUrl) + .putExtra(WebApkConstants.EXTRA_SOURCE, source) + .putExtra(WebApkConstants.EXTRA_WEBAPK_PACKAGE_NAME, packageName); try { - Class<?> hostBrowserLauncherClass = - webApkClassLoader.loadClass(HOST_BROWSER_LAUNCHER_CLASS_NAME); - Method launchMethod = hostBrowserLauncherClass.getMethod( - "launch", Context.class, Intent.class, Bundle.class); - Object hostBrowserLauncherInstance = hostBrowserLauncherClass.newInstance(); - Bundle bundle = new Bundle(); - bundle.putInt(KEY_APP_ICON_ID, R.mipmap.app_icon); - launchMethod.invoke(hostBrowserLauncherInstance, this, getIntent(), bundle); + startActivity(intent); return true; - } catch (Exception e) { + } catch (ActivityNotFoundException e) { Log.w(TAG, "Unable to launch browser in WebAPK mode."); e.printStackTrace(); return false;
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index de93a48..acec309 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -10522,6 +10522,12 @@ <message name="IDS_COOKIES_INDEXED_DBS" desc="Label for Indexed Databases (name of an HTML standard)"> Indexed databases </message> + <message name="IDS_COOKIES_MEDIA_LICENSE" desc="The text shown when there is an Media License in the Cookies table"> + Media license + </message> + <message name="IDS_COOKIES_MEDIA_LICENSES" desc="Label for Media Licenses"> + Media licenses + </message> <message name="IDS_COOKIES_FILE_SYSTEM" desc="The text shown when there is a file system (name of an HTML standard) in the Cookies table"> File system </message>
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 0f6574be..839ac3d 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -177,12 +177,28 @@ <message name="IDS_SETTINGS_SET_WALLPAPER" desc="Name of the control which allows the user to set the wallpaper."> Wallpaper </message> - <message name="IDS_SETTINGS_THEME" desc="Name of the control which allows the user to get a theme for the browser."> - Theme + <message name="IDS_SETTINGS_THEMES" desc="Name of the control which allows the user to get a theme for the browser."> + Themes </message> - <message name="IDS_SETTINGS_RESET_TO_DEFAULT_THEME" desc="Name of the control which resets the browser theme back to the default theme."> - Reset to default - </message> + <if expr="is_linux and not chromeos"> + <message name="IDS_SETTINGS_SYSTEM_THEME" desc="Text of the label describing the system (GTK+) browser theme on Linux"> + GTK+ + </message> + <message name="IDS_SETTINGS_USE_SYSTEM_THEME" desc="Text of the button that switches the browser theme to the system (GTK+) theme on Linux"> + Use GTK+ + </message> + <message name="IDS_SETTINGS_CLASSIC_THEME" desc="Text of the label describing the classic browser theme on Linux"> + Classic + </message> + <message name="IDS_SETTINGS_USE_CLASSIC_THEME" desc="Text of the button that switches the browser theme to the classic theme on Linux"> + Use Classic + </message> + </if> + <if expr="not is_linux or chromeos"> + <message name="IDS_SETTINGS_RESET_TO_DEFAULT_THEME" desc="Name of the control which resets the browser theme back to the default theme."> + Reset to default + </message> + </if> <message name="IDS_SETTINGS_SHOW_HOME_BUTTON" desc="Label for the checkbox which enables or disables showing the home button in the toolbar."> Show home button </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 8edef1e..9a031b0 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -153,6 +153,8 @@ "browsing_data/browsing_data_indexed_db_helper.h", "browsing_data/browsing_data_local_storage_helper.cc", "browsing_data/browsing_data_local_storage_helper.h", + "browsing_data/browsing_data_media_license_helper.cc", + "browsing_data/browsing_data_media_license_helper.h", "browsing_data/browsing_data_quota_helper.cc", "browsing_data/browsing_data_quota_helper.h", "browsing_data/browsing_data_quota_helper_impl.cc", @@ -553,6 +555,8 @@ "media/webrtc/window_icon_util_chromeos.cc", "media/webrtc/window_icon_util_mac.mm", "media/webrtc/window_icon_util_win.cc", + "memory/chrome_memory_coordinator_delegate.cc", + "memory/chrome_memory_coordinator_delegate.h", "memory_details.cc", "memory_details.h", "memory_details_android.cc", @@ -1413,8 +1417,8 @@ "//courgette:courgette_lib", "//crypto", "//crypto:platform", + "//device/base", "//device/bluetooth:mojo", - "//device/core", "//device/usb/mojo", "//device/usb/public/interfaces", "//google_apis", @@ -4031,6 +4035,8 @@ "browsing_data/mock_browsing_data_indexed_db_helper.h", "browsing_data/mock_browsing_data_local_storage_helper.cc", "browsing_data/mock_browsing_data_local_storage_helper.h", + "browsing_data/mock_browsing_data_media_license_helper.cc", + "browsing_data/mock_browsing_data_media_license_helper.h", "browsing_data/mock_browsing_data_quota_helper.cc", "browsing_data/mock_browsing_data_quota_helper.h", "browsing_data/mock_browsing_data_service_worker_helper.cc",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index 7bf8e774..0cd88589 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS
@@ -13,8 +13,8 @@ "+components", "+content/public/browser", "+courgette", + "+device/base", "+device/bluetooth", - "+device/core", "+device/geolocation", "+device/hid", "+device/media_transfer_protocol", @@ -114,4 +114,4 @@ 'chrome_security_exploit_browsertest\.cc' : [ '+content/common', ], -} \ No newline at end of file +}
diff --git a/chrome/browser/android/banners/app_banner_infobar_delegate_android.cc b/chrome/browser/android/banners/app_banner_infobar_delegate_android.cc index 0997b5d3..8398b12 100644 --- a/chrome/browser/android/banners/app_banner_infobar_delegate_android.cc +++ b/chrome/browser/android/banners/app_banner_infobar_delegate_android.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/android/shortcut_helper.h" #include "chrome/browser/android/shortcut_info.h" #include "chrome/browser/android/tab_android.h" +#include "chrome/browser/android/webapk/chrome_webapk_host.h" #include "chrome/browser/android/webapk/webapk_installer.h" #include "chrome/browser/banners/app_banner_manager.h" #include "chrome/browser/banners/app_banner_metrics.h" @@ -55,13 +56,20 @@ std::unique_ptr<ShortcutInfo> shortcut_info, std::unique_ptr<SkBitmap> icon, int event_request_id, - bool is_webapk, webapk::InstallSource webapk_install_source) { + bool is_webapk = ChromeWebApkHost::AreWebApkEnabled(); + std::string webapk_package_name = ""; + if (is_webapk) { + webapk_package_name = ShortcutHelper::QueryWebApkPackage( + web_contents->GetLastCommittedURL()); + } + bool is_webapk_already_installed = !webapk_package_name.empty(); const GURL& url = shortcut_info->url; auto infobar_delegate = base::WrapUnique(new banners::AppBannerInfoBarDelegateAndroid( weak_manager, app_title, std::move(shortcut_info), std::move(icon), - event_request_id, is_webapk, webapk_install_source)); + event_request_id, is_webapk, is_webapk_already_installed, + webapk_install_source)); auto raw_delegate = infobar_delegate.get(); auto infobar = base::MakeUnique<AppBannerInfoBarAndroid>( std::move(infobar_delegate), url, is_webapk); @@ -71,8 +79,12 @@ if (is_webapk) { if (webapk_install_source == webapk::INSTALL_SOURCE_MENU) { - raw_delegate->Accept(); - webapk::TrackInstallInfoBarShown(webapk::WEBAPK_INFOBAR_SHOWN_FROM_MENU); + webapk::TrackInstallInfoBarShown( + webapk::WEBAPK_INFOBAR_SHOWN_FROM_MENU); + if (is_webapk_already_installed) + raw_delegate->UpdateStateForInstalledWebAPK(webapk_package_name); + else + raw_delegate->Accept(); } else { webapk::TrackInstallInfoBarShown( webapk::WEBAPK_INFOBAR_SHOWN_FROM_BANNER); @@ -189,6 +201,19 @@ return AcceptWebApp(web_contents); } +void AppBannerInfoBarDelegateAndroid::UpdateStateForInstalledWebAPK( + const std::string& webapk_package_name) { + JNIEnv* env = base::android::AttachCurrentThread(); + ScopedJavaLocalRef<jstring> java_webapk_package_name = + base::android::ConvertUTF8ToJavaString(env, webapk_package_name); + Java_AppBannerInfoBarDelegateAndroid_setWebApkInstallingState( + env, java_delegate_, false); + Java_AppBannerInfoBarDelegateAndroid_setWebApkPackageName( + env, java_delegate_, java_webapk_package_name); + UpdateInstallState(env, nullptr); + install_state_ = INSTALLED; +} + AppBannerInfoBarDelegateAndroid::AppBannerInfoBarDelegateAndroid( base::WeakPtr<AppBannerManager> weak_manager, const base::string16& app_title, @@ -196,6 +221,7 @@ std::unique_ptr<SkBitmap> icon, int event_request_id, bool is_webapk, + bool is_webapk_already_installed, webapk::InstallSource webapk_install_source) : weak_manager_(weak_manager), app_title_(app_title), @@ -204,6 +230,7 @@ event_request_id_(event_request_id), has_user_interaction_(false), is_webapk_(is_webapk), + is_webapk_already_installed_(is_webapk_already_installed), install_state_(INSTALL_NOT_STARTED), webapk_install_source_(webapk_install_source), weak_ptr_factory_(this) { @@ -286,51 +313,40 @@ return true; JNIEnv* env = base::android::AttachCurrentThread(); - // |webapk_package_name_| is set when the WebAPK has finished installing. - // If the |webapk_package_name_| is empty, it means the "Add to Homescreen" - // button is pressed, so request WebAPK installation. Otherwise, it means - // the "Open" button is pressed, so open the installed WebAPK. - if (!webapk_package_name_.empty()) { - // Open the WebAPK. - ScopedJavaLocalRef<jstring> java_webapk_package_name = - base::android::ConvertUTF8ToJavaString(env, webapk_package_name_); - Java_AppBannerInfoBarDelegateAndroid_openWebApk(env, java_delegate_, - java_webapk_package_name); - webapk::TrackUserAction(webapk::USER_ACTION_INSTALLED_OPEN); + + // If the WebAPK is installed and the "Open" button is clicked, open the + // WebAPK. + if (install_state_ == INSTALLED) { + Java_AppBannerInfoBarDelegateAndroid_openWebApk(env, java_delegate_); + if (is_webapk_already_installed_) + webapk::TrackUserAction(webapk::USER_ACTION_OPEN); + else + webapk::TrackUserAction(webapk::USER_ACTION_INSTALLED_OPEN); SendBannerAccepted(web_contents, "web"); return true; } - // Check whether the WebAPK has been installed. - std::string installed_webapk_package_name = - ShortcutHelper::QueryWebApkPackage(web_contents->GetLastCommittedURL()); - if (installed_webapk_package_name.empty()) { - // Request install the WebAPK. - install_state_ = INSTALLING; - TrackUserResponse(USER_RESPONSE_WEB_APP_ACCEPTED); - webapk::TrackInstallSource(webapk_install_source_); - AppBannerSettingsHelper::RecordBannerInstallEvent( - web_contents, shortcut_info_->url.spec(), AppBannerSettingsHelper::WEB); - - Java_AppBannerInfoBarDelegateAndroid_setWebApkInstallingState( - env, java_delegate_, true); - UpdateInstallState(env, nullptr); - WebApkInstaller::FinishCallback callback = - base::Bind(&AppBannerInfoBarDelegateAndroid::OnWebApkInstallFinished, - weak_ptr_factory_.GetWeakPtr()); - ShortcutHelper::InstallWebApkWithSkBitmap(web_contents->GetBrowserContext(), - *shortcut_info_, - *icon_.get(), callback); - SendBannerAccepted(web_contents, "web"); - - // Prevent the infobar from disappearing, because the infobar will show - // "Adding" during the installation process. - return false; - } - - // Bypass the installation since WebAPK is already installed. + // If the WebAPK is not installed and the "Add to Home Screen" button is + // clicked, install the WebAPK. + install_state_ = INSTALLING; TrackUserResponse(USER_RESPONSE_WEB_APP_ACCEPTED); - OnWebApkInstallFinished(true, installed_webapk_package_name); + webapk::TrackInstallSource(webapk_install_source_); + AppBannerSettingsHelper::RecordBannerInstallEvent( + web_contents, shortcut_info_->url.spec(), AppBannerSettingsHelper::WEB); + + Java_AppBannerInfoBarDelegateAndroid_setWebApkInstallingState( + env, java_delegate_, true); + UpdateInstallState(env, nullptr); + WebApkInstaller::FinishCallback callback = + base::Bind(&AppBannerInfoBarDelegateAndroid::OnWebApkInstallFinished, + weak_ptr_factory_.GetWeakPtr()); + ShortcutHelper::InstallWebApkWithSkBitmap(web_contents->GetBrowserContext(), + *shortcut_info_, + *icon_.get(), callback); + SendBannerAccepted(web_contents, "web"); + + // Prevent the infobar from disappearing, because the infobar will show + // "Adding" during the installation process. return false; } @@ -357,15 +373,7 @@ return; } - webapk_package_name_ = webapk_package_name; - ScopedJavaLocalRef<jstring> java_webapk_package_name = - base::android::ConvertUTF8ToJavaString(env, webapk_package_name); - Java_AppBannerInfoBarDelegateAndroid_setWebApkInstallingState( - env, java_delegate_, false); - Java_AppBannerInfoBarDelegateAndroid_setWebApkPackageName( - env, java_delegate_, java_webapk_package_name); - UpdateInstallState(env, nullptr); - install_state_ = INSTALLED; + UpdateStateForInstalledWebAPK(webapk_package_name); webapk::TrackInstallEvent(webapk::INSTALL_COMPLETED); } @@ -376,9 +384,12 @@ } else if (install_state == INSTALLING) { webapk::TrackInstallEvent(webapk::INFOBAR_DISMISSED_DURING_INSTALLATION); } else if (install_state == INSTALLED) { - // When |install_state| is INSTALLED, the install Event will be recorded in + // If WebAPK is installed from this banner, TrackInstallEvent() is called in // OnWebApkInstallFinished(). - webapk::TrackUserAction(webapk::USER_ACTION_INSTALLED_OPEN_DISMISS); + if (is_webapk_already_installed_) + webapk::TrackUserAction(webapk::USER_ACTION_OPEN_DISMISS); + else + webapk::TrackUserAction(webapk::USER_ACTION_INSTALLED_OPEN_DISMISS); } }
diff --git a/chrome/browser/android/banners/app_banner_infobar_delegate_android.h b/chrome/browser/android/banners/app_banner_infobar_delegate_android.h index 0dc66c5c..c305bb9 100644 --- a/chrome/browser/android/banners/app_banner_infobar_delegate_android.h +++ b/chrome/browser/android/banners/app_banner_infobar_delegate_android.h
@@ -39,7 +39,6 @@ std::unique_ptr<ShortcutInfo> info, std::unique_ptr<SkBitmap> icon, int event_request_id, - bool is_webapk, webapk::InstallSource webapk_install_source); // Creates an infobar and delegate for promoting the installation of an @@ -73,6 +72,9 @@ // ConfirmInfoBarDelegate: bool Accept() override; + // Update the AppBannerInfoBarAndroid with installed WebAPK's information. + void UpdateStateForInstalledWebAPK(const std::string& webapk_package_name); + private: // The states of a WebAPK installation, where the infobar is displayed during // the entire installation process. This state is used to correctly record @@ -91,6 +93,7 @@ std::unique_ptr<SkBitmap> icon, int event_request_id, bool is_webapk, + bool is_webapk_already_installed, webapk::InstallSource webapk_install_source); // Delegate for promoting an Android app. @@ -106,16 +109,15 @@ bool AcceptNativeApp(content::WebContents* web_contents); bool AcceptWebApp(content::WebContents* web_contents); - // When user accepts to install a WebAPK, this function sends a request - // to the WebAPK Server to create a WebAPK and install it. It returns - // false to prevent infobar from disappearing when installation starts. - // When user clicks the Open button after the intallation is compelete, this - // function launches the installed WebAPK and returns true. + // Called when the OK button on a WebAPK infobar is pressed. If the WebAPK is + // already installed, opens it; otherwise, installs it. Returns whether the + // infobar should be closed as a result of the button press. bool AcceptWebApk(content::WebContents* web_contents); void SendBannerAccepted(content::WebContents* web_contents, const std::string& platform); - void OnWebApkInstallFinished(bool success, const std::string& webapk_package); + void OnWebApkInstallFinished(bool success, + const std::string& webapk_package_name); void TrackWebApkInstallationDismissEvents(InstallState install_state); // ConfirmInfoBarDelegate: @@ -143,8 +145,8 @@ int event_request_id_; bool has_user_interaction_; - std::string webapk_package_name_; bool is_webapk_; + bool is_webapk_already_installed_; // Indicates the current state of a WebAPK installation. InstallState install_state_;
diff --git a/chrome/browser/android/banners/app_banner_manager_android.cc b/chrome/browser/android/banners/app_banner_manager_android.cc index d298606..7d2c80b4 100644 --- a/chrome/browser/android/banners/app_banner_manager_android.cc +++ b/chrome/browser/android/banners/app_banner_manager_android.cc
@@ -199,7 +199,6 @@ contents, GetWeakPtr(), app_title_, CreateShortcutInfo(manifest_url_, manifest_, icon_url_), std::move(icon_), event_request_id(), - ChromeWebApkHost::AreWebApkEnabled(), webapk::INSTALL_SOURCE_BANNER)) { RecordDidShowBanner("AppBanner.WebApp.Shown"); TrackDisplayEvent(DISPLAY_EVENT_WEB_APP_BANNER_CREATED);
diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc index 81d8e6a..3fe7eb7f 100644 --- a/chrome/browser/android/chrome_jni_registrar.cc +++ b/chrome/browser/android/chrome_jni_registrar.cc
@@ -104,7 +104,6 @@ #include "chrome/browser/android/webapk/webapk_installer.h" #include "chrome/browser/android/webapk/webapk_update_manager.h" #include "chrome/browser/android/webapps/add_to_homescreen_manager.h" -#include "chrome/browser/android/webapps/webapp_registry.h" #include "chrome/browser/autofill/android/personal_data_manager_android.h" #include "chrome/browser/dom_distiller/dom_distiller_service_factory_android.h" #include "chrome/browser/dom_distiller/tab_utils_android.h" @@ -390,7 +389,6 @@ {"WarmupManager", RegisterWarmupManager}, {"WebApkInstaller", WebApkInstaller::Register}, {"WebApkUpdateManager", WebApkUpdateManager::Register}, - {"WebappRegistry", WebappRegistry::RegisterWebappRegistry}, {"WebContentsFactory", RegisterWebContentsFactory}, {"WebsitePreferenceBridge", RegisterWebsitePreferenceBridge}, {"WebsiteSettingsPopupAndroid",
diff --git a/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc b/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc index 8d484ebf2..cff1e74 100644 --- a/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc +++ b/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc
@@ -311,7 +311,7 @@ EXPECT_EQ(0U, all_pages().size()); } -TEST_F(RecentTabHelperTest, DownloadRequest) { +TEST_F(RecentTabHelperTest, DISABLED_DownloadRequest) { NavigateAndCommit(kTestPageUrl); recent_tab_helper()->ObserveAndDownloadCurrentPage( ClientId("download", "id1"), 153l);
diff --git a/chrome/browser/android/preferences/website_preference_bridge.cc b/chrome/browser/android/preferences/website_preference_bridge.cc index 509ab44e1..4ab1bf2 100644 --- a/chrome/browser/android/preferences/website_preference_bridge.cc +++ b/chrome/browser/android/preferences/website_preference_bridge.cc
@@ -531,7 +531,7 @@ new BrowsingDataCookieHelper(profile_->GetRequestContext()), new BrowsingDataDatabaseHelper(profile_), new BrowsingDataLocalStorageHelper(profile_), - NULL, + nullptr, new BrowsingDataAppCacheHelper(profile_), new BrowsingDataIndexedDBHelper(indexed_db_context), BrowsingDataFileSystemHelper::Create(file_system_context), @@ -539,7 +539,8 @@ BrowsingDataChannelIDHelper::Create(profile_->GetRequestContext()), new BrowsingDataServiceWorkerHelper(service_worker_context), new BrowsingDataCacheStorageHelper(cache_storage_context), - NULL); + nullptr, + nullptr); cookies_tree_model_.reset(new CookiesTreeModel( container, profile_->GetExtensionSpecialStoragePolicy()));
diff --git a/chrome/browser/android/webapk/manifest_upgrade_detector_fetcher.cc b/chrome/browser/android/webapk/manifest_upgrade_detector_fetcher.cc index 00bc822..bff110e 100644 --- a/chrome/browser/android/webapk/manifest_upgrade_detector_fetcher.cc +++ b/chrome/browser/android/webapk/manifest_upgrade_detector_fetcher.cc
@@ -13,7 +13,6 @@ #include "chrome/browser/android/webapk/webapk_web_manifest_checker.h" #include "chrome/browser/installable/installable_manager.h" #include "chrome/browser/profiles/profile.h" -#include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/manifest.h" #include "jni/ManifestUpgradeDetectorFetcher_jni.h" @@ -87,14 +86,24 @@ const JavaParamRef<jobject>& obj, const JavaParamRef<jobject>& java_web_contents) { ReplaceWebContents(env, obj, java_web_contents); + if (!web_contents()->IsLoading()) + FetchInstallableData(); } -void ManifestUpgradeDetectorFetcher::DidFinishLoad( - content::RenderFrameHost* render_frame_host, - const GURL& validated_url) { - if (render_frame_host->GetParent()) +void ManifestUpgradeDetectorFetcher::DidStopLoading() { + FetchInstallableData(); +} + +void ManifestUpgradeDetectorFetcher::FetchInstallableData() { + GURL url = web_contents()->GetLastCommittedURL(); + + // DidStopLoading() can be called multiple times for a single URL. Only fetch + // installable data the first time. + if (url == last_fetched_url_) return; - if (!IsInScope(validated_url, scope_)) + last_fetched_url_ = url; + + if (!IsInScope(url, scope_)) return; InstallableParams params;
diff --git a/chrome/browser/android/webapk/manifest_upgrade_detector_fetcher.h b/chrome/browser/android/webapk/manifest_upgrade_detector_fetcher.h index faac564..6f090a846 100644 --- a/chrome/browser/android/webapk/manifest_upgrade_detector_fetcher.h +++ b/chrome/browser/android/webapk/manifest_upgrade_detector_fetcher.h
@@ -53,8 +53,10 @@ ~ManifestUpgradeDetectorFetcher() override; // content::WebContentsObserver: - void DidFinishLoad(content::RenderFrameHost* render_frame_host, - const GURL& validated_url) override; + void DidStopLoading() override; + + // Fetches the installable data. + void FetchInstallableData(); // Called once the installable data has been fetched. void OnDidGetInstallableData(const InstallableData& installable_data); @@ -75,6 +77,9 @@ // The WebAPK's Web Manifest URL that the detector is looking for. const GURL web_manifest_url_; + // The URL for which the installable data is being fetched / was last fetched. + GURL last_fetched_url_; + // Downloads app icon and computes Murmur2 hash. std::unique_ptr<WebApkIconHasher> icon_hasher_;
diff --git a/chrome/browser/android/webapps/add_to_homescreen_manager.cc b/chrome/browser/android/webapps/add_to_homescreen_manager.cc index 2b972540..40af6b5d 100644 --- a/chrome/browser/android/webapps/add_to_homescreen_manager.cc +++ b/chrome/browser/android/webapps/add_to_homescreen_manager.cc
@@ -173,8 +173,7 @@ banners::AppBannerInfoBarDelegateAndroid::Create( data_fetcher_->web_contents(), nullptr, info.user_title, base::MakeUnique<ShortcutInfo>(info), base::MakeUnique<SkBitmap>(icon), - -1 /* event_request_id */, true /* is_webapk */, - webapk::INSTALL_SOURCE_MENU); + -1 /* event_request_id */, webapk::INSTALL_SOURCE_MENU); } SkBitmap AddToHomescreenManager::FinalizeLauncherIconInBackground(
diff --git a/chrome/browser/android/webapps/webapp_registry.cc b/chrome/browser/android/webapps/webapp_registry.cc index 3b3616b1..bb909c8 100644 --- a/chrome/browser/android/webapps/webapp_registry.cc +++ b/chrome/browser/android/webapps/webapp_registry.cc
@@ -4,70 +4,26 @@ #include "chrome/browser/android/webapps/webapp_registry.h" -#include <jni.h> - -#include "base/android/context_utils.h" #include "base/android/jni_android.h" -#include "base/callback.h" #include "chrome/browser/android/browsing_data/url_filter_bridge.h" -#include "chrome/browser/io_thread.h" -#include "content/public/browser/browser_thread.h" #include "jni/WebappRegistry_jni.h" using base::android::JavaParamRef; void WebappRegistry::UnregisterWebappsForUrls( - const base::Callback<bool(const GURL&)>& url_filter, - const base::Closure& callback) { - JNIEnv* env = base::android::AttachCurrentThread(); - // TODO(msramek): Consider implementing a wrapper class that will call and - // destroy this closure from Java, eliminating the need for - // OnWebappsUnregistered() and OnClearedWebappHistory() callbacks. - uintptr_t callback_pointer = reinterpret_cast<uintptr_t>( - new base::Closure(callback)); - - // We will destroy |filter_bridge| from its Java counterpart before calling - // back OnWebappsUnregistered(). + const base::Callback<bool(const GURL&)>& url_filter) { + // |filter_bridge| is destroyed from its Java counterpart. UrlFilterBridge* filter_bridge = new UrlFilterBridge(url_filter); - Java_WebappRegistry_unregisterWebappsForUrls(env, filter_bridge->j_bridge(), - callback_pointer); + Java_WebappRegistry_unregisterWebappsForUrls( + base::android::AttachCurrentThread(), filter_bridge->j_bridge()); } void WebappRegistry::ClearWebappHistoryForUrls( - const base::Callback<bool(const GURL&)>& url_filter, - const base::Closure& callback) { - JNIEnv* env = base::android::AttachCurrentThread(); - uintptr_t callback_pointer = reinterpret_cast<uintptr_t>( - new base::Closure(callback)); - - // We will destroy |filter_bridge| from its Java counterpart before calling - // back OnClearedWebappHistory(). + const base::Callback<bool(const GURL&)>& url_filter) { + // |filter_bridge| is destroyed from its Java counterpart. UrlFilterBridge* filter_bridge = new UrlFilterBridge(url_filter); - Java_WebappRegistry_clearWebappHistoryForUrls(env, filter_bridge->j_bridge(), - callback_pointer); -} - -// Callback used by Java when all web apps have been unregistered. -void OnWebappsUnregistered(JNIEnv* env, - const JavaParamRef<jclass>& clazz, - jlong jcallback) { - base::Closure* callback = reinterpret_cast<base::Closure*>(jcallback); - callback->Run(); - delete callback; -} - -// Callback used by Java when all web app last used times have been cleared. -void OnClearedWebappHistory(JNIEnv* env, - const JavaParamRef<jclass>& clazz, - jlong jcallback) { - base::Closure* callback = reinterpret_cast<base::Closure*>(jcallback); - callback->Run(); - delete callback; -} - -// static -bool WebappRegistry::RegisterWebappRegistry(JNIEnv* env) { - return RegisterNativesImpl(env); + Java_WebappRegistry_clearWebappHistoryForUrls( + base::android::AttachCurrentThread(), filter_bridge->j_bridge()); }
diff --git a/chrome/browser/android/webapps/webapp_registry.h b/chrome/browser/android/webapps/webapp_registry.h index 029a3db..2752710 100644 --- a/chrome/browser/android/webapps/webapp_registry.h +++ b/chrome/browser/android/webapps/webapp_registry.h
@@ -5,8 +5,6 @@ #ifndef CHROME_BROWSER_ANDROID_WEBAPPS_WEBAPP_REGISTRY_H_ #define CHROME_BROWSER_ANDROID_WEBAPPS_WEBAPP_REGISTRY_H_ -#include "base/android/jni_android.h" -#include "base/android/scoped_java_ref.h" #include "base/callback_forward.h" #include "base/macros.h" @@ -22,19 +20,14 @@ WebappRegistry() { } virtual ~WebappRegistry() { } - // Registers JNI hooks. - static bool RegisterWebappRegistry(JNIEnv* env); - // Cleans up data stored by web apps on URLs matching |url_filter|. virtual void UnregisterWebappsForUrls( - const base::Callback<bool(const GURL&)>& url_filter, - const base::Closure& callback); + const base::Callback<bool(const GURL&)>& url_filter); // Removes history data (last used time and URLs) stored by web apps with // URLs matching |url_filter|, whilst leaving other data intact. virtual void ClearWebappHistoryForUrls( - const base::Callback<bool(const GURL&)>& url_filter, - const base::Closure& callback); + const base::Callback<bool(const GURL&)>& url_filter); private: DISALLOW_COPY_AND_ASSIGN(WebappRegistry);
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 0f5f7ee..fad4f7c4 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -99,7 +99,8 @@ <include name="IDR_BLUETOOTH_INTERNALS_CSS" file="resources\bluetooth_internals\bluetooth_internals.css" type="BINDATA" compress="gzip" /> <include name="IDR_BLUETOOTH_INTERNALS_HTML" file="resources\bluetooth_internals\bluetooth_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" /> <include name="IDR_BLUETOOTH_INTERNALS_JS" file="resources\bluetooth_internals\bluetooth_internals.js" type="BINDATA" compress="gzip" /> - <include name="IDR_BLUETOOTH_MOJO_JS" file="${root_gen_dir}\device\bluetooth\public\interfaces\adapter.mojom.js" use_base_dir="false" type="BINDATA" compress="gzip" /> + <include name="IDR_BLUETOOTH_ADAPTER_MOJO_JS" file="${root_gen_dir}\device\bluetooth\public\interfaces\adapter.mojom.js" use_base_dir="false" type="BINDATA" compress="gzip" /> + <include name="IDR_BLUETOOTH_DEVICE_MOJO_JS" file="${root_gen_dir}\device\bluetooth\public\interfaces\device.mojom.js" use_base_dir="false" type="BINDATA" compress="gzip" /> <include name="IDR_BOOKMARKS_MANIFEST" file="resources\bookmark_manager\manifest.json" type="BINDATA" /> <if expr="is_posix and not is_macosx and not is_ios"> <include name="IDR_CERTIFICATE_VIEWER_HTML" file="resources\certificate_viewer.html" type="BINDATA" />
diff --git a/chrome/browser/browsing_data/browsing_data_media_license_helper.cc b/chrome/browser/browsing_data/browsing_data_media_license_helper.cc new file mode 100644 index 0000000..653af7ff --- /dev/null +++ b/chrome/browser/browsing_data/browsing_data_media_license_helper.cc
@@ -0,0 +1,148 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/browsing_data/browsing_data_media_license_helper.h" + +#include <memory> +#include <set> + +#include "base/bind.h" +#include "base/location.h" +#include "base/macros.h" +#include "base/sequenced_task_runner.h" +#include "chrome/browser/browsing_data/browsing_data_helper.h" +#include "content/public/browser/browser_thread.h" +#include "storage/browser/fileapi/file_system_context.h" +#include "storage/browser/fileapi/file_system_quota_util.h" +#include "storage/browser/fileapi/plugin_private_file_system_backend.h" +#include "storage/common/fileapi/file_system_types.h" + +using content::BrowserThread; + +namespace { + +// An implementation of the BrowsingDataMediaLicenseHelper interface that +// determine data on media licenses in a given |filesystem_context| and +// returns a list of MediaLicenseInfo items to a client. +class BrowsingDataMediaLicenseHelperImpl + : public BrowsingDataMediaLicenseHelper { + public: + // BrowsingDataMediaLicenseHelper implementation + explicit BrowsingDataMediaLicenseHelperImpl( + storage::FileSystemContext* filesystem_context); + void StartFetching(const FetchCallback& callback) final; + void DeleteMediaLicenseOrigin(const GURL& origin) final; + + private: + ~BrowsingDataMediaLicenseHelperImpl() final; + + // Enumerates all filesystem files, storing the resulting list into + // file_system_file_ for later use. This must be called on the file + // task runner. + void FetchMediaLicenseInfoOnFileTaskRunner(const FetchCallback& callback); + + // Deletes all file systems associated with |origin|. This must be called on + // the file task runner. + void DeleteMediaLicenseOriginOnFileTaskRunner(const GURL& origin); + + // Returns the file task runner for the |filesystem_context_|. + base::SequencedTaskRunner* file_task_runner() { + return filesystem_context_->default_file_task_runner(); + } + + // Keep a reference to the FileSystemContext object for the current profile + // for use on the file task runner. + scoped_refptr<storage::FileSystemContext> filesystem_context_; + + DISALLOW_COPY_AND_ASSIGN(BrowsingDataMediaLicenseHelperImpl); +}; + +BrowsingDataMediaLicenseHelperImpl::BrowsingDataMediaLicenseHelperImpl( + storage::FileSystemContext* filesystem_context) + : filesystem_context_(filesystem_context) { + DCHECK(filesystem_context_.get()); +} + +BrowsingDataMediaLicenseHelperImpl::~BrowsingDataMediaLicenseHelperImpl() {} + +void BrowsingDataMediaLicenseHelperImpl::StartFetching( + const FetchCallback& callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(!callback.is_null()); + file_task_runner()->PostTask( + FROM_HERE, base::Bind(&BrowsingDataMediaLicenseHelperImpl:: + FetchMediaLicenseInfoOnFileTaskRunner, + this, callback)); +} + +void BrowsingDataMediaLicenseHelperImpl::DeleteMediaLicenseOrigin( + const GURL& origin) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + file_task_runner()->PostTask( + FROM_HERE, base::Bind(&BrowsingDataMediaLicenseHelperImpl:: + DeleteMediaLicenseOriginOnFileTaskRunner, + this, origin)); +} + +void BrowsingDataMediaLicenseHelperImpl::FetchMediaLicenseInfoOnFileTaskRunner( + const FetchCallback& callback) { + DCHECK(file_task_runner()->RunsTasksOnCurrentThread()); + DCHECK(!callback.is_null()); + + const storage::FileSystemType kType = storage::kFileSystemTypePluginPrivate; + + storage::PluginPrivateFileSystemBackend* backend = + static_cast<storage::PluginPrivateFileSystemBackend*>( + filesystem_context_->GetFileSystemBackend(kType)); + + // Determine the set of origins used. + std::set<GURL> origins; + std::list<MediaLicenseInfo> result; + backend->GetOriginsForTypeOnFileTaskRunner(kType, &origins); + for (const GURL& origin : origins) { + if (!BrowsingDataHelper::HasWebScheme(origin)) + continue; // Non-websafe state is not considered browsing data. + + int64_t size; + base::Time last_modified_time; + backend->GetOriginDetailsOnFileTaskRunner(filesystem_context_.get(), origin, + &size, &last_modified_time); + result.push_back(MediaLicenseInfo(origin, size, last_modified_time)); + } + + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(callback, result)); +} + +void BrowsingDataMediaLicenseHelperImpl:: + DeleteMediaLicenseOriginOnFileTaskRunner(const GURL& origin) { + DCHECK(file_task_runner()->RunsTasksOnCurrentThread()); + + const storage::FileSystemType kType = storage::kFileSystemTypePluginPrivate; + storage::FileSystemBackend* backend = + filesystem_context_->GetFileSystemBackend(kType); + storage::FileSystemQuotaUtil* quota_util = backend->GetQuotaUtil(); + quota_util->DeleteOriginDataOnFileTaskRunner( + filesystem_context_.get(), filesystem_context_->quota_manager_proxy(), + origin, kType); +} + +} // namespace + +BrowsingDataMediaLicenseHelper::MediaLicenseInfo::MediaLicenseInfo( + const GURL& origin, + int64_t size, + base::Time last_modified_time) + : origin(origin), size(size), last_modified_time(last_modified_time) {} + +BrowsingDataMediaLicenseHelper::MediaLicenseInfo::MediaLicenseInfo( + const MediaLicenseInfo& other) = default; + +BrowsingDataMediaLicenseHelper::MediaLicenseInfo::~MediaLicenseInfo() {} + +// static +BrowsingDataMediaLicenseHelper* BrowsingDataMediaLicenseHelper::Create( + storage::FileSystemContext* filesystem_context) { + return new BrowsingDataMediaLicenseHelperImpl(filesystem_context); +}
diff --git a/chrome/browser/browsing_data/browsing_data_media_license_helper.h b/chrome/browser/browsing_data/browsing_data_media_license_helper.h new file mode 100644 index 0000000..d1cecfd --- /dev/null +++ b/chrome/browser/browsing_data/browsing_data_media_license_helper.h
@@ -0,0 +1,82 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_BROWSING_DATA_BROWSING_DATA_MEDIA_LICENSE_HELPER_H_ +#define CHROME_BROWSER_BROWSING_DATA_BROWSING_DATA_MEDIA_LICENSE_HELPER_H_ + +#include <stdint.h> +#include <list> + +#include "base/callback.h" +#include "base/memory/ref_counted.h" +#include "base/time/time.h" +#include "url/gurl.h" + +namespace storage { +class FileSystemContext; +} + +// Defines an interface for classes that deal with aggregating and deleting +// media licenses. +// BrowsingDataMediaLicenseHelper instances for a specific profile should +// be created via the static Create method. Each instance will lazily fetch +// data when a client calls StartFetching from the UI thread, and will +// notify the client via a supplied callback when the data is available. +// +// The client's callback is passed a list of MediaLicenseInfo objects +// containing usage information for each origin's media licenses. +class BrowsingDataMediaLicenseHelper + : public base::RefCountedThreadSafe<BrowsingDataMediaLicenseHelper> { + public: + // Detailed information about a media license, including it's origin GURL + // and the amount of data (in bytes). + struct MediaLicenseInfo { + MediaLicenseInfo(const GURL& origin, + int64_t size, + base::Time last_modified_time); + MediaLicenseInfo(const MediaLicenseInfo& other); + ~MediaLicenseInfo(); + + // The origin for which the information is relevant. + GURL origin; + // Size (in bytes). + int64_t size; + // Last modified time. + base::Time last_modified_time; + }; + + using FetchCallback = + base::Callback<void(const std::list<MediaLicenseInfo>&)>; + + // Creates a BrowsingDataMediaLicenseHelper instance for the media + // licenses stored in |profile|'s user data directory. The + // BrowsingDataMediaLicenseHelper object will hold a reference to the + // Profile that's passed in, but is not responsible for destroying it. + // + // The BrowsingDataMediaLicenseHelper will not change the profile itself, + // but can modify data it contains (by removing media licenses). + static BrowsingDataMediaLicenseHelper* Create( + storage::FileSystemContext* file_system_context); + + // Starts the process of fetching media license data, which will call + // |callback| upon completion, passing it a constant list of + // MediaLicenseInfo objects. StartFetching must be called only in the UI + // thread; the provided Callback will likewise be executed asynchronously + // on the UI thread. Obtaining the data will occur asynchronously on the + // FILE thread. + virtual void StartFetching(const FetchCallback& callback) = 0; + + // Deletes any media licenses associated with |origin| from the disk. + // Deletion will occur asynchronously on the FILE thread, but this function + // must be called only on the UI thread. + virtual void DeleteMediaLicenseOrigin(const GURL& origin) = 0; + + protected: + friend class base::RefCountedThreadSafe<BrowsingDataMediaLicenseHelper>; + + BrowsingDataMediaLicenseHelper() {} + virtual ~BrowsingDataMediaLicenseHelper() {} +}; + +#endif // CHROME_BROWSER_BROWSING_DATA_BROWSING_DATA_MEDIA_LICENSE_HELPER_H_
diff --git a/chrome/browser/browsing_data/browsing_data_media_license_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_media_license_helper_unittest.cc new file mode 100644 index 0000000..8f4782e --- /dev/null +++ b/chrome/browser/browsing_data/browsing_data_media_license_helper_unittest.cc
@@ -0,0 +1,348 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stddef.h> +#include <algorithm> +#include <memory> +#include <string> +#include <vector> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/files/file_util.h" +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/stl_util.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/browsing_data/browsing_data_media_license_helper.h" +#include "chrome/test/base/testing_profile.h" +#include "content/public/browser/storage_partition.h" +#include "content/public/test/test_browser_thread.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "ppapi/shared_impl/ppapi_constants.h" +#include "storage/browser/fileapi/async_file_util.h" +#include "storage/browser/fileapi/file_system_context.h" +#include "storage/browser/fileapi/file_system_operation_context.h" +#include "storage/browser/fileapi/file_system_url.h" +#include "storage/browser/fileapi/isolated_context.h" +#include "storage/browser/quota/quota_manager.h" +#include "storage/common/fileapi/file_system_types.h" +#include "storage/common/fileapi/file_system_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +using content::BrowserContext; +using content::BrowserThread; + +namespace { + +// We'll use these three distinct origins for testing, both as strings and as +// GURLs in appropriate contexts. +const char kTestOrigin1[] = "http://host1:1/"; +const char kTestOrigin2[] = "http://host2:2/"; +const char kTestOrigin3[] = "http://host3:1/"; + +const GURL kOrigin1(kTestOrigin1); +const GURL kOrigin2(kTestOrigin2); +const GURL kOrigin3(kTestOrigin3); + +const char kWidevineCdmPluginId[] = "application_x-ppapi-widevine-cdm"; +const char kClearKeyCdmPluginId[] = "application_x-ppapi-clearkey-cdm"; + +class AwaitCompletionHelper { + public: + AwaitCompletionHelper() : start_(false), already_quit_(false) {} + virtual ~AwaitCompletionHelper() {} + + void BlockUntilNotified() { + if (!already_quit_) { + DCHECK(!start_); + start_ = true; + base::RunLoop().Run(); + } else { + DCHECK(!start_); + already_quit_ = false; + } + } + + base::Closure NotifyClosure() { + return base::Bind(&AwaitCompletionHelper::Notify, base::Unretained(this)); + } + + private: + void Notify() { + if (start_) { + DCHECK(!already_quit_); + base::MessageLoop::current()->QuitWhenIdle(); + start_ = false; + } else { + DCHECK(!already_quit_); + already_quit_ = true; + } + } + + // Helps prevent from running message_loop, if the callback invoked + // immediately. + bool start_; + bool already_quit_; + + DISALLOW_COPY_AND_ASSIGN(AwaitCompletionHelper); +}; + +// The FileSystem APIs are all asynchronous; this testing class wraps up the +// boilerplate code necessary to deal with waiting for responses. In a nutshell, +// any async call whose response we want to test ought to be followed by a call +// to BlockUntilNotified(), which will block until Notify() is called. +class BrowsingDataMediaLicenseHelperTest : public testing::Test { + public: + BrowsingDataMediaLicenseHelperTest() { + now_ = base::Time::Now(); + profile_.reset(new TestingProfile()); + filesystem_context_ = + BrowserContext::GetDefaultStoragePartition(profile_.get()) + ->GetFileSystemContext(); + helper_ = BrowsingDataMediaLicenseHelper::Create(filesystem_context_); + base::RunLoop().RunUntilIdle(); + } + + ~BrowsingDataMediaLicenseHelperTest() override { + // Avoid memory leaks. + profile_.reset(); + base::RunLoop().RunUntilIdle(); + } + + // Calls StartFetching() on the test's BrowsingDataMediaLicenseHelper + // object, then blocks until the callback is executed. + void FetchMediaLicenses() { + AwaitCompletionHelper await_completion; + helper_->StartFetching( + base::Bind(&BrowsingDataMediaLicenseHelperTest::OnFetchMediaLicenses, + base::Unretained(this), await_completion.NotifyClosure())); + await_completion.BlockUntilNotified(); + } + + // Callback that should be executed in response to StartFetching(), and stores + // found file systems locally so that they are available via GetFileSystems(). + void OnFetchMediaLicenses( + const base::Closure& done_cb, + const std::list<BrowsingDataMediaLicenseHelper::MediaLicenseInfo>& + media_license_info_list) { + media_license_info_list_.reset( + new std::list<BrowsingDataMediaLicenseHelper::MediaLicenseInfo>( + media_license_info_list)); + done_cb.Run(); + } + + // Add some files to the PluginPrivateFileSystem. They are created as follows: + // kOrigin1 - ClearKey - 1 file - timestamp 10 days ago + // kOrigin2 - Widevine - 2 files - timestamps now and 60 days ago + // kOrigin3 - Widevine - 2 files - timestamps 20 and 30 days ago + virtual void PopulateTestMediaLicenseData() { + const base::Time ten_days_ago = now_ - base::TimeDelta::FromDays(10); + const base::Time twenty_days_ago = now_ - base::TimeDelta::FromDays(20); + const base::Time thirty_days_ago = now_ - base::TimeDelta::FromDays(30); + const base::Time sixty_days_ago = now_ - base::TimeDelta::FromDays(60); + + std::string clearkey_fsid = + CreateFileSystem(kClearKeyCdmPluginId, kOrigin1); + storage::FileSystemURL clearkey_file = + CreateFile(kOrigin1, clearkey_fsid, "foo"); + SetFileTimestamp(clearkey_file, ten_days_ago); + + std::string widevine_fsid = + CreateFileSystem(kWidevineCdmPluginId, kOrigin2); + storage::FileSystemURL widevine_file1 = + CreateFile(kOrigin2, widevine_fsid, "bar1"); + storage::FileSystemURL widevine_file2 = + CreateFile(kOrigin2, widevine_fsid, "bar2"); + SetFileTimestamp(widevine_file1, now_); + SetFileTimestamp(widevine_file2, sixty_days_ago); + + std::string widevine_fsid2 = + CreateFileSystem(kWidevineCdmPluginId, kOrigin3); + storage::FileSystemURL widevine_file3 = + CreateFile(kOrigin3, widevine_fsid2, "test1"); + storage::FileSystemURL widevine_file4 = + CreateFile(kOrigin3, widevine_fsid2, "test2"); + SetFileTimestamp(widevine_file3, twenty_days_ago); + SetFileTimestamp(widevine_file4, thirty_days_ago); + } + + const base::Time Now() { return now_; } + + void DeleteMediaLicenseOrigin(const GURL& origin) { + helper_->DeleteMediaLicenseOrigin(origin); + } + + std::list<BrowsingDataMediaLicenseHelper::MediaLicenseInfo>* + ReturnedMediaLicenseInfo() const { + return media_license_info_list_.get(); + } + + private: + // Creates a PluginPrivateFileSystem for the |plugin_name| and |origin| + // provided. Returns the file system ID for the created + // PluginPrivateFileSystem. + std::string CreateFileSystem(const std::string& plugin_name, + const GURL& origin) { + AwaitCompletionHelper await_completion; + std::string fsid = storage::IsolatedContext::GetInstance() + ->RegisterFileSystemForVirtualPath( + storage::kFileSystemTypePluginPrivate, + ppapi::kPluginPrivateRootName, base::FilePath()); + EXPECT_TRUE(storage::ValidateIsolatedFileSystemId(fsid)); + filesystem_context_->OpenPluginPrivateFileSystem( + origin, storage::kFileSystemTypePluginPrivate, fsid, plugin_name, + storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, + base::Bind(&BrowsingDataMediaLicenseHelperTest::OnFileSystemOpened, + base::Unretained(this), await_completion.NotifyClosure())); + await_completion.BlockUntilNotified(); + return fsid; + } + + void OnFileSystemOpened(const base::Closure& done_cb, + base::File::Error result) { + EXPECT_EQ(base::File::FILE_OK, result) << base::File::ErrorToString(result); + done_cb.Run(); + } + + // Creates a file named |file_name| in the PluginPrivateFileSystem identified + // by |origin| and |fsid|. The file is empty (so size = 0). Returns the URL + // for the created file. The file must not already exist or the test will + // fail. + storage::FileSystemURL CreateFile(const GURL& origin, + const std::string& fsid, + const std::string& file_name) { + AwaitCompletionHelper await_completion; + std::string root = storage::GetIsolatedFileSystemRootURIString( + origin, fsid, ppapi::kPluginPrivateRootName); + storage::FileSystemURL file_url = + filesystem_context_->CrackURL(GURL(root + file_name)); + storage::AsyncFileUtil* file_util = filesystem_context_->GetAsyncFileUtil( + storage::kFileSystemTypePluginPrivate); + std::unique_ptr<storage::FileSystemOperationContext> operation_context = + base::WrapUnique( + new storage::FileSystemOperationContext(filesystem_context_)); + operation_context->set_allowed_bytes_growth( + storage::QuotaManager::kNoLimit); + file_util->EnsureFileExists( + std::move(operation_context), file_url, + base::Bind(&BrowsingDataMediaLicenseHelperTest::OnFileCreated, + base::Unretained(this), await_completion.NotifyClosure())); + await_completion.BlockUntilNotified(); + return file_url; + } + + void OnFileCreated(const base::Closure& done_cb, + base::File::Error result, + bool created) { + EXPECT_EQ(base::File::FILE_OK, result) << base::File::ErrorToString(result); + EXPECT_TRUE(created); + done_cb.Run(); + } + + // Sets the last_access_time and last_modified_time to |time_stamp| on the + // file specified by |file_url|. The file must already exist. + void SetFileTimestamp(const storage::FileSystemURL& file_url, + const base::Time& time_stamp) { + AwaitCompletionHelper await_completion; + storage::AsyncFileUtil* file_util = filesystem_context_->GetAsyncFileUtil( + storage::kFileSystemTypePluginPrivate); + std::unique_ptr<storage::FileSystemOperationContext> operation_context = + base::WrapUnique( + new storage::FileSystemOperationContext(filesystem_context_)); + file_util->Touch( + std::move(operation_context), file_url, time_stamp, time_stamp, + base::Bind(&BrowsingDataMediaLicenseHelperTest::OnFileTouched, + base::Unretained(this), await_completion.NotifyClosure())); + await_completion.BlockUntilNotified(); + } + + void OnFileTouched(const base::Closure& done_cb, base::File::Error result) { + EXPECT_EQ(base::File::FILE_OK, result) << base::File::ErrorToString(result); + done_cb.Run(); + } + + content::TestBrowserThreadBundle thread_bundle_; + std::unique_ptr<TestingProfile> profile_; + scoped_refptr<BrowsingDataMediaLicenseHelper> helper_; + + // Keep a fixed "now" so that we can compare timestamps. + base::Time now_; + + // We don't own this pointer. + storage::FileSystemContext* filesystem_context_; + + // Storage to pass information back from callbacks. + std::unique_ptr<std::list<BrowsingDataMediaLicenseHelper::MediaLicenseInfo>> + media_license_info_list_; + + DISALLOW_COPY_AND_ASSIGN(BrowsingDataMediaLicenseHelperTest); +}; + +// Verifies that the BrowsingDataMediaLicenseHelper correctly handles an empty +// filesystem. +TEST_F(BrowsingDataMediaLicenseHelperTest, Empty) { + FetchMediaLicenses(); + EXPECT_EQ(0u, ReturnedMediaLicenseInfo()->size()); +} + +// Verifies that the BrowsingDataMediaLicenseHelper correctly finds the test +// data, and that each media license returned contains the expected data. +TEST_F(BrowsingDataMediaLicenseHelperTest, FetchData) { + PopulateTestMediaLicenseData(); + + FetchMediaLicenses(); + EXPECT_EQ(3u, ReturnedMediaLicenseInfo()->size()); + + // Order is arbitrary, verify both origins. + bool test_hosts_found[] = {false, false, false}; + for (const auto& info : *ReturnedMediaLicenseInfo()) { + if (info.origin == kOrigin1) { + EXPECT_FALSE(test_hosts_found[0]); + test_hosts_found[0] = true; + EXPECT_EQ(0u, info.size); + // Single file for origin1 should be 10 days ago. + EXPECT_EQ(10, (Now() - info.last_modified_time).InDays()); + } else if (info.origin == kOrigin2) { + EXPECT_FALSE(test_hosts_found[1]); + test_hosts_found[1] = true; + EXPECT_EQ(0u, info.size); + // Files for origin2 are now and 60 days ago, so it should report now. + EXPECT_EQ(0, (Now() - info.last_modified_time).InDays()); + } else if (info.origin == kOrigin3) { + EXPECT_FALSE(test_hosts_found[2]); + test_hosts_found[2] = true; + EXPECT_EQ(0u, info.size); + // Files for origin3 are 20 and 30 days ago, so it should report 20. + EXPECT_EQ(20, (Now() - info.last_modified_time).InDays()); + } else { + ADD_FAILURE() << info.origin.spec() << " isn't an origin we added."; + } + } + for (size_t i = 0; i < arraysize(test_hosts_found); i++) { + EXPECT_TRUE(test_hosts_found[i]); + } +} + +// Verifies that the BrowsingDataMediaLicenseHelper correctly deletes media +// licenses via DeleteMediaLicenseOrigin(). +TEST_F(BrowsingDataMediaLicenseHelperTest, DeleteData) { + PopulateTestMediaLicenseData(); + + DeleteMediaLicenseOrigin(kOrigin1); + DeleteMediaLicenseOrigin(kOrigin2); + + FetchMediaLicenses(); + EXPECT_EQ(1u, ReturnedMediaLicenseInfo()->size()); + + BrowsingDataMediaLicenseHelper::MediaLicenseInfo info = + *(ReturnedMediaLicenseInfo()->begin()); + EXPECT_EQ(kOrigin3, info.origin); + EXPECT_EQ(0u, info.size); + EXPECT_EQ(20, (Now() - info.last_modified_time).InDays()); +} + +} // namespace
diff --git a/chrome/browser/browsing_data/browsing_data_remover.cc b/chrome/browser/browsing_data/browsing_data_remover.cc index fcd6a79..e6b80a48 100644 --- a/chrome/browser/browsing_data/browsing_data_remover.cc +++ b/chrome/browser/browsing_data/browsing_data_remover.cc
@@ -702,13 +702,8 @@ } // Clear the history information (last launch time and origin URL) of any - // registered webapps. The webapp_registry makes a JNI call into a Java-side - // AsyncTask, so don't wait for the reply. - waiting_for_clear_webapp_history_ = true; - webapp_registry_->ClearWebappHistoryForUrls( - filter, - base::Bind(&BrowsingDataRemover::OnClearedWebappHistory, - weak_ptr_factory_.GetWeakPtr())); + // registered webapps. + webapp_registry_->ClearWebappHistoryForUrls(filter); #endif data_reduction_proxy::DataReductionProxySettings* @@ -1160,15 +1155,9 @@ } #if BUILDFLAG(ANDROID_JAVA_UI) - if (remove_mask & REMOVE_WEBAPP_DATA) { - // Clear all data associated with registered webapps. The webapp_registry - // makes a JNI call into a Java-side AsyncTask, so don't wait for the reply. - waiting_for_clear_webapp_data_ = true; - webapp_registry_->UnregisterWebappsForUrls( - filter, - base::Bind(&BrowsingDataRemover::OnClearedWebappData, - weak_ptr_factory_.GetWeakPtr())); - } + // Clear all data associated with registered webapps. + if (remove_mask & REMOVE_WEBAPP_DATA) + webapp_registry_->UnregisterWebappsForUrls(filter); // For now we're considering offline pages as cache, so if we're removing // cache we should remove offline pages as well. @@ -1276,8 +1265,6 @@ !waiting_for_clear_pnacl_cache_ && #if BUILDFLAG(ANDROID_JAVA_UI) !waiting_for_clear_precache_history_ && - !waiting_for_clear_webapp_data_ && - !waiting_for_clear_webapp_history_ && !waiting_for_clear_offline_page_data_ && #endif #if defined(ENABLE_WEBRTC) @@ -1536,18 +1523,6 @@ NotifyIfDone(); } -void BrowsingDataRemover::OnClearedWebappData() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - waiting_for_clear_webapp_data_ = false; - NotifyIfDone(); -} - -void BrowsingDataRemover::OnClearedWebappHistory() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - waiting_for_clear_webapp_history_ = false; - NotifyIfDone(); -} - void BrowsingDataRemover::OnClearedOfflinePageData( offline_pages::OfflinePageModel::DeletePageResult result) { DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/chrome/browser/browsing_data/browsing_data_remover.h b/chrome/browser/browsing_data/browsing_data_remover.h index cd8d4b28..0487471 100644 --- a/chrome/browser/browsing_data/browsing_data_remover.h +++ b/chrome/browser/browsing_data/browsing_data_remover.h
@@ -463,12 +463,6 @@ // Callback on UI thread when the precache history has been cleared. void OnClearedPrecacheHistory(); - // Callback on UI thread when the webapp data has been cleared. - void OnClearedWebappData(); - - // Callback on UI thread when the webapp history has been cleared. - void OnClearedWebappHistory(); - // Callback on UI thread when the offline page data has been cleared. void OnClearedOfflinePageData( offline_pages::OfflinePageModel::DeletePageResult result); @@ -545,8 +539,6 @@ bool waiting_for_clear_pnacl_cache_ = false; #if BUILDFLAG(ANDROID_JAVA_UI) bool waiting_for_clear_precache_history_ = false; - bool waiting_for_clear_webapp_data_ = false; - bool waiting_for_clear_webapp_history_ = false; bool waiting_for_clear_offline_page_data_ = false; #endif bool waiting_for_clear_storage_partition_data_ = false;
diff --git a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc index 76886a3..787b46f 100644 --- a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc +++ b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
@@ -318,19 +318,13 @@ TestWebappRegistry() : WebappRegistry() { } void UnregisterWebappsForUrls( - const base::Callback<bool(const GURL&)>& url_filter, - const base::Closure& callback) override { - // Mocks out a JNI call and runs the callback as a delayed task. - BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE, callback, - base::TimeDelta::FromMilliseconds(10)); + const base::Callback<bool(const GURL&)>& url_filter) override { + // Mocks out a JNI call. } void ClearWebappHistoryForUrls( - const base::Callback<bool(const GURL&)>& url_filter, - const base::Closure& callback) override { - // Mocks out a JNI call and runs the callback as a delayed task. - BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE, callback, - base::TimeDelta::FromMilliseconds(10)); + const base::Callback<bool(const GURL&)>& url_filter) override { + // Mocks out a JNI call. } }; #endif
diff --git a/chrome/browser/browsing_data/cookies_tree_model.cc b/chrome/browser/browsing_data/cookies_tree_model.cc index 2d713e28..bfcf2fb 100644 --- a/chrome/browser/browsing_data/cookies_tree_model.cc +++ b/chrome/browser/browsing_data/cookies_tree_model.cc
@@ -144,6 +144,7 @@ case CookieTreeNode::DetailedInfo::TYPE_QUOTA: case CookieTreeNode::DetailedInfo::TYPE_CHANNEL_ID: case CookieTreeNode::DetailedInfo::TYPE_FLASH_LSO: + case CookieTreeNode::DetailedInfo::TYPE_MEDIA_LICENSE: return false; default: break; @@ -279,6 +280,15 @@ return *this; } +CookieTreeNode::DetailedInfo& CookieTreeNode::DetailedInfo::InitMediaLicense( + const BrowsingDataMediaLicenseHelper::MediaLicenseInfo* + media_license_info) { + Init(TYPE_MEDIA_LICENSE); + this->media_license_info = media_license_info; + this->origin = media_license_info->origin; + return *this; +} + /////////////////////////////////////////////////////////////////////////////// // CookieTreeNode, public: @@ -583,6 +593,32 @@ } /////////////////////////////////////////////////////////////////////////////// +// CookieTreeMediaLicenseNode, public: + +CookieTreeMediaLicenseNode::CookieTreeMediaLicenseNode( + const std::list<BrowsingDataMediaLicenseHelper::MediaLicenseInfo>::iterator + media_license_info) + : CookieTreeNode(base::UTF8ToUTF16(media_license_info->origin.spec())), + media_license_info_(media_license_info) {} + +CookieTreeMediaLicenseNode::~CookieTreeMediaLicenseNode() {} + +void CookieTreeMediaLicenseNode::DeleteStoredObjects() { + LocalDataContainer* container = GetLocalDataContainerForNode(this); + + if (container) { + container->media_license_helper_->DeleteMediaLicenseOrigin( + media_license_info_->origin); + container->media_license_info_list_.erase(media_license_info_); + } +} + +CookieTreeNode::DetailedInfo CookieTreeMediaLicenseNode::GetDetailedInfo() + const { + return DetailedInfo().InitMediaLicense(&*media_license_info_); +} + +/////////////////////////////////////////////////////////////////////////////// // CookieTreeRootNode, public: CookieTreeRootNode::CookieTreeRootNode(CookiesTreeModel* model) @@ -749,6 +785,15 @@ return flash_lso_child_; } +CookieTreeMediaLicensesNode* +CookieTreeHostNode::GetOrCreateMediaLicensesNode() { + if (media_licenses_child_) + return media_licenses_child_; + media_licenses_child_ = new CookieTreeMediaLicensesNode(); + AddChildSortedByTitle(base::WrapUnique(media_licenses_child_)); + return media_licenses_child_; +} + void CookieTreeHostNode::CreateContentException( content_settings::CookieSettings* cookie_settings, ContentSetting setting) const { @@ -935,6 +980,18 @@ } /////////////////////////////////////////////////////////////////////////////// +// CookieTreeMediaLicensesNode +CookieTreeMediaLicensesNode::CookieTreeMediaLicensesNode() + : CookieTreeNode(l10n_util::GetStringUTF16(IDS_COOKIES_MEDIA_LICENSES)) {} + +CookieTreeMediaLicensesNode::~CookieTreeMediaLicensesNode() {} + +CookieTreeNode::DetailedInfo CookieTreeMediaLicensesNode::GetDetailedInfo() + const { + return DetailedInfo().Init(DetailedInfo::TYPE_MEDIA_LICENSES); +} + +/////////////////////////////////////////////////////////////////////////////// // ScopedBatchUpdateNotifier CookiesTreeModel::ScopedBatchUpdateNotifier::ScopedBatchUpdateNotifier( CookiesTreeModel* model, @@ -1028,6 +1085,7 @@ case CookieTreeNode::DetailedInfo::TYPE_FILE_SYSTEM: case CookieTreeNode::DetailedInfo::TYPE_SERVICE_WORKER: case CookieTreeNode::DetailedInfo::TYPE_CACHE_STORAGE: + case CookieTreeNode::DetailedInfo::TYPE_MEDIA_LICENSE: return DATABASE; case CookieTreeNode::DetailedInfo::TYPE_QUOTA: return -1; @@ -1171,6 +1229,11 @@ PopulateFlashLSOInfoWithFilter(container, ¬ifier, base::string16()); } +void CookiesTreeModel::PopulateMediaLicenseInfo(LocalDataContainer* container) { + ScopedBatchUpdateNotifier notifier(this, GetRoot()); + PopulateMediaLicenseInfoWithFilter(container, ¬ifier, base::string16()); +} + void CookiesTreeModel::PopulateAppCacheInfoWithFilter( LocalDataContainer* container, ScopedBatchUpdateNotifier* notifier, @@ -1493,6 +1556,33 @@ } } +void CookiesTreeModel::PopulateMediaLicenseInfoWithFilter( + LocalDataContainer* container, + ScopedBatchUpdateNotifier* notifier, + const base::string16& filter) { + CookieTreeRootNode* root = static_cast<CookieTreeRootNode*>(GetRoot()); + + if (container->media_license_info_list_.empty()) + return; + + notifier->StartBatchUpdate(); + for (MediaLicenseInfoList::iterator media_license_info = + container->media_license_info_list_.begin(); + media_license_info != container->media_license_info_list_.end(); + ++media_license_info) { + GURL origin(media_license_info->origin); + + if (filter.empty() || (CookieTreeHostNode::TitleForUrl(origin).find( + filter) != base::string16::npos)) { + CookieTreeHostNode* host_node = root->GetOrCreateHostNode(origin); + CookieTreeMediaLicensesNode* media_licenses_node = + host_node->GetOrCreateMediaLicensesNode(); + media_licenses_node->AddMediaLicenseNode( + base::MakeUnique<CookieTreeMediaLicenseNode>(media_license_info)); + } + } +} + void CookiesTreeModel::SetBatchExpectation(int batches_expected, bool reset) { batches_expected_ = batches_expected; if (reset) {
diff --git a/chrome/browser/browsing_data/cookies_tree_model.h b/chrome/browser/browsing_data/cookies_tree_model.h index 2d81901..96205bb 100644 --- a/chrome/browser/browsing_data/cookies_tree_model.h +++ b/chrome/browser/browsing_data/cookies_tree_model.h
@@ -53,6 +53,8 @@ class CookieTreeIndexedDBsNode; class CookieTreeLocalStorageNode; class CookieTreeLocalStoragesNode; +class CookieTreeMediaLicenseNode; +class CookieTreeMediaLicensesNode; class CookieTreeQuotaNode; class CookieTreeServiceWorkerNode; class CookieTreeServiceWorkersNode; @@ -109,6 +111,8 @@ TYPE_CACHE_STORAGES, // This is used for CookieTreeCacheStoragesNode. TYPE_CACHE_STORAGE, // This is used for CookieTreeCacheStorageNode. TYPE_FLASH_LSO, // This is used for CookieTreeFlashLSONode. + TYPE_MEDIA_LICENSES, // This is used for CookieTreeMediaLicensesNode. + TYPE_MEDIA_LICENSE, // This is used for CookieTreeMediaLicenseNode. }; DetailedInfo(); @@ -141,6 +145,9 @@ DetailedInfo& InitCacheStorage( const content::CacheStorageUsageInfo* cache_storage_info); DetailedInfo& InitFlashLSO(const std::string& flash_lso_domain); + DetailedInfo& InitMediaLicense( + const BrowsingDataMediaLicenseHelper::MediaLicenseInfo* + media_license_info); NodeType node_type; GURL origin; @@ -159,6 +166,8 @@ const content::ServiceWorkerUsageInfo* service_worker_info = nullptr; const content::CacheStorageUsageInfo* cache_storage_info = nullptr; std::string flash_lso_domain; + const BrowsingDataMediaLicenseHelper::MediaLicenseInfo* media_license_info = + nullptr; }; CookieTreeNode() {} @@ -229,6 +238,7 @@ CookieTreeQuotaNode* UpdateOrCreateQuotaNode( std::list<BrowsingDataQuotaHelper::QuotaInfo>::iterator quota_info); CookieTreeFlashLSONode* GetOrCreateFlashLSONode(const std::string& domain); + CookieTreeMediaLicensesNode* GetOrCreateMediaLicensesNode(); std::string canonicalized_host() const { return canonicalized_host_; } @@ -260,6 +270,7 @@ CookieTreeServiceWorkersNode* service_workers_child_ = nullptr; CookieTreeCacheStoragesNode* cache_storages_child_ = nullptr; CookieTreeFlashLSONode* flash_lso_child_ = nullptr; + CookieTreeMediaLicensesNode* media_licenses_child_ = nullptr; // The URL for which this node was initially created. GURL url_; @@ -684,6 +695,45 @@ DISALLOW_COPY_AND_ASSIGN(CookieTreeFlashLSONode); }; +// CookieTreeMediaLicenseNode ----------------------------------------------- +class CookieTreeMediaLicenseNode : public CookieTreeNode { + public: + friend class CookieTreeMediaLicensesNode; + + // |media_license_info| is expected to remain valid as long as the + // CookieTreeMediaLicenseNode is valid. + explicit CookieTreeMediaLicenseNode( + const std::list<BrowsingDataMediaLicenseHelper::MediaLicenseInfo>:: + iterator media_license_info); + ~CookieTreeMediaLicenseNode() override; + + void DeleteStoredObjects() override; + DetailedInfo GetDetailedInfo() const override; + + private: + // |media_license_info_| is expected to remain valid as long as the + // CookieTreeMediaLicenseNode is valid. + std::list<BrowsingDataMediaLicenseHelper::MediaLicenseInfo>::iterator + media_license_info_; + + DISALLOW_COPY_AND_ASSIGN(CookieTreeMediaLicenseNode); +}; + +class CookieTreeMediaLicensesNode : public CookieTreeNode { + public: + CookieTreeMediaLicensesNode(); + ~CookieTreeMediaLicensesNode() override; + + DetailedInfo GetDetailedInfo() const override; + + void AddMediaLicenseNode(std::unique_ptr<CookieTreeMediaLicenseNode> child) { + AddChildSortedByTitle(std::move(child)); + } + + private: + DISALLOW_COPY_AND_ASSIGN(CookieTreeMediaLicensesNode); +}; + // CookiesTreeModel ----------------------------------------------------------- class CookiesTreeModel : public ui::TreeNodeModel<CookieTreeNode> { public: @@ -773,6 +823,7 @@ void PopulateServiceWorkerUsageInfo(LocalDataContainer* container); void PopulateCacheStorageUsageInfo(LocalDataContainer* container); void PopulateFlashLSOInfo(LocalDataContainer* container); + void PopulateMediaLicenseInfo(LocalDataContainer* container); BrowsingDataCookieHelper* GetCookieHelper(const std::string& app_id); LocalDataContainer* data_container() { @@ -849,6 +900,9 @@ void PopulateFlashLSOInfoWithFilter(LocalDataContainer* container, ScopedBatchUpdateNotifier* notifier, const base::string16& filter); + void PopulateMediaLicenseInfoWithFilter(LocalDataContainer* container, + ScopedBatchUpdateNotifier* notifier, + const base::string16& filter); #if defined(ENABLE_EXTENSIONS) // The extension special storage policy; see ExtensionsProtectingNode() above.
diff --git a/chrome/browser/browsing_data/cookies_tree_model_unittest.cc b/chrome/browser/browsing_data/cookies_tree_model_unittest.cc index ee95f9e..35074ff 100644 --- a/chrome/browser/browsing_data/cookies_tree_model_unittest.cc +++ b/chrome/browser/browsing_data/cookies_tree_model_unittest.cc
@@ -18,6 +18,7 @@ #include "chrome/browser/browsing_data/mock_browsing_data_flash_lso_helper.h" #include "chrome/browser/browsing_data/mock_browsing_data_indexed_db_helper.h" #include "chrome/browser/browsing_data/mock_browsing_data_local_storage_helper.h" +#include "chrome/browser/browsing_data/mock_browsing_data_media_license_helper.h" #include "chrome/browser/browsing_data/mock_browsing_data_quota_helper.h" #include "chrome/browser/browsing_data/mock_browsing_data_service_worker_helper.h" #include "chrome/browser/content_settings/cookie_settings_factory.h" @@ -81,6 +82,8 @@ new MockBrowsingDataCacheStorageHelper(profile_.get()); mock_browsing_data_flash_lso_helper_ = new MockBrowsingDataFlashLSOHelper(profile_.get()); + mock_browsing_data_media_license_helper_ = + new MockBrowsingDataMediaLicenseHelper(profile_.get()); #if defined(ENABLE_EXTENSIONS) special_storage_policy_ = @@ -100,6 +103,7 @@ mock_browsing_data_local_storage_helper_ = nullptr; mock_browsing_data_database_helper_ = nullptr; mock_browsing_data_flash_lso_helper_ = nullptr; + mock_browsing_data_media_license_helper_ = nullptr; base::RunLoop().RunUntilIdle(); } std::unique_ptr<CookiesTreeModel> CreateCookiesTreeModelWithInitialSample() { @@ -115,7 +119,8 @@ mock_browsing_data_channel_id_helper_, mock_browsing_data_service_worker_helper_, mock_browsing_data_cache_storage_helper_, - mock_browsing_data_flash_lso_helper_); + mock_browsing_data_flash_lso_helper_, + mock_browsing_data_media_license_helper_); CookiesTreeModel* cookies_model = new CookiesTreeModel(container, special_storage_policy()); @@ -149,21 +154,23 @@ mock_browsing_data_cache_storage_helper_->Notify(); mock_browsing_data_flash_lso_helper_->AddFlashLSODomain("xyz.com"); mock_browsing_data_flash_lso_helper_->Notify(); + mock_browsing_data_media_license_helper_->AddMediaLicenseSamples(); + mock_browsing_data_media_license_helper_->Notify(); { SCOPED_TRACE( "Initial State 3 cookies, 2 databases, 2 local storages, " "2 session storages, 2 indexed DBs, 3 filesystems, " "2 quotas, 2 server bound certs, 2 service workers, " - "2 cache storages, 1 Flash LSO"); - // 65 because there's the root, then + "2 cache storages, 1 Flash LSO, 2 media licenses"); + // 71 because there's the root, then // cshost1 -> cache storage -> https://cshost1:1/ // cshost2 -> cache storage -> https://cshost2:2/ // foo1 -> cookies -> a, // foo2 -> cookies -> b, // foo3 -> cookies -> c, - // dbhost1 -> database -> db1, - // dbhost2 -> database -> db2, + // gdbhost1 -> database -> db1, + // gdbhost2 -> database -> db2, // host1 -> localstorage -> http://host1:1/, // -> sessionstorage -> http://host1:1/, // host2 -> localstorage -> http://host2:2/. @@ -173,6 +180,8 @@ // fshost1 -> filesystem -> http://fshost1:1/, // fshost2 -> filesystem -> http://fshost2:1/, // fshost3 -> filesystem -> http://fshost3:1/, + // media1 -> media_licenses -> media_license, + // media2 -> media_licenses -> media_license, // quotahost1 -> quotahost1, // quotahost2 -> quotahost2, // sbc1 -> sbcerts -> sbc1, @@ -180,7 +189,7 @@ // swhost1 -> service worker -> https://swhost1:1 // swhost2 -> service worker -> https://swhost1:2 // xyz.com -> flash_lsos - EXPECT_EQ(65, cookies_model->GetRoot()->GetTotalNodeCount()); + EXPECT_EQ(71, cookies_model->GetRoot()->GetTotalNodeCount()); EXPECT_EQ("A,B,C", GetDisplayedCookies(cookies_model)); EXPECT_EQ("db1,db2", GetDisplayedDatabases(cookies_model)); EXPECT_EQ("http://host1:1/,http://host2:2/", @@ -201,6 +210,8 @@ GetDisplayedCacheStorages(cookies_model)); EXPECT_EQ("xyz.com", GetDisplayedFlashLSOs(cookies_model)); + EXPECT_EQ("https://media1/,https://media2/", + GetDisplayedMediaLicenses(cookies_model)); } return base::WrapUnique(cookies_model); } @@ -283,6 +294,8 @@ return node->GetDetailedInfo().cache_storage_info->origin.spec() + ","; case CookieTreeNode::DetailedInfo::TYPE_FLASH_LSO: return node->GetDetailedInfo().flash_lso_domain + ","; + case CookieTreeNode::DetailedInfo::TYPE_MEDIA_LICENSE: + return node->GetDetailedInfo().media_license_info->origin.spec() + ","; default: return std::string(); } @@ -337,6 +350,11 @@ node, CookieTreeNode::DetailedInfo::TYPE_FLASH_LSO); } + std::string GetMediaLicensesOfChildren(const CookieTreeNode* node) { + return GetNodesOfChildren(node, + CookieTreeNode::DetailedInfo::TYPE_MEDIA_LICENSE); + } + // Get the nodes names displayed in the view (if we had one) in the order // they are displayed, as a comma seperated string. // Ex: EXPECT_STREQ("X,Y", GetDisplayedNodes(cookies_view, type).c_str()); @@ -410,6 +428,11 @@ cookies_model, CookieTreeNode::DetailedInfo::TYPE_FLASH_LSO); } + std::string GetDisplayedMediaLicenses(CookiesTreeModel* cookies_model) { + return GetDisplayedNodes(cookies_model, + CookieTreeNode::DetailedInfo::TYPE_MEDIA_LICENSE); + } + // Do not call on the root. void DeleteStoredObjects(CookieTreeNode* node) { node->DeleteStoredObjects(); @@ -453,6 +476,8 @@ mock_browsing_data_cache_storage_helper_; scoped_refptr<MockBrowsingDataFlashLSOHelper> mock_browsing_data_flash_lso_helper_; + scoped_refptr<MockBrowsingDataMediaLicenseHelper> + mock_browsing_data_media_license_helper_; #if defined(ENABLE_EXTENSIONS) scoped_refptr<ExtensionSpecialStoragePolicy> special_storage_policy_; @@ -488,6 +513,8 @@ GetDisplayedServiceWorkers(cookies_model.get())); EXPECT_EQ("xyz.com", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("https://media1/,https://media2/", + GetDisplayedMediaLicenses(cookies_model.get())); } mock_browsing_data_cookie_helper_->Reset(); @@ -521,6 +548,7 @@ EXPECT_TRUE(mock_browsing_data_service_worker_helper_->AllDeleted()); EXPECT_TRUE(mock_browsing_data_cache_storage_helper_->AllDeleted()); EXPECT_TRUE(mock_browsing_data_flash_lso_helper_->AllDeleted()); + EXPECT_TRUE(mock_browsing_data_media_license_helper_->AllDeleted()); } } @@ -544,18 +572,21 @@ // 11. `host2` // 12. `idbhost1` // 13. `idbhost2` - // 14. `quotahost1` - // 15. `quotahost2` - // 16. `sbc1` - // 17. `sbc2` - // 18. `swhost1` - // 19. `swhost2` - // 20. `xyz.com` + // 14. `media1` + // 15. `media2` + // 16. `quotahost1` + // 17. `quotahost2` + // 18. `sbc1` + // 19. `sbc2` + // 20. `swhost1` + // 21. `swhost2` + // 22. `xyz.com` // // Here, we'll remove them one by one, starting from the end, and - // check that the state makes sense. + // check that the state makes sense. Initially there are 71 total nodes. - DeleteStoredObjects(cookies_model->GetRoot()->GetChild(20)); + // xyz.com -> flash_lsos (2 nodes) + DeleteStoredObjects(cookies_model->GetRoot()->GetChild(22)); { SCOPED_TRACE("`xyz.com` removed."); EXPECT_STREQ("A,B,C", GetDisplayedCookies(cookies_model.get()).c_str()); @@ -577,9 +608,13 @@ EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); - EXPECT_EQ(63, cookies_model->GetRoot()->GetTotalNodeCount()); + EXPECT_EQ("https://media1/,https://media2/", + GetDisplayedMediaLicenses(cookies_model.get())); + EXPECT_EQ(69, cookies_model->GetRoot()->GetTotalNodeCount()); } - DeleteStoredObjects(cookies_model->GetRoot()->GetChild(19)); + + // swhost2 -> service worker -> https://swhost1:2 (3 objects) + DeleteStoredObjects(cookies_model->GetRoot()->GetChild(21)); { SCOPED_TRACE("`swhost2` removed."); EXPECT_STREQ("A,B,C", GetDisplayedCookies(cookies_model.get()).c_str()); @@ -599,9 +634,13 @@ EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); - EXPECT_EQ(60, cookies_model->GetRoot()->GetTotalNodeCount()); + EXPECT_EQ("https://media1/,https://media2/", + GetDisplayedMediaLicenses(cookies_model.get())); + EXPECT_EQ(66, cookies_model->GetRoot()->GetTotalNodeCount()); } - DeleteStoredObjects(cookies_model->GetRoot()->GetChild(18)); + + // swhost1 -> service worker -> https://swhost1:1 (3 nodes) + DeleteStoredObjects(cookies_model->GetRoot()->GetChild(20)); { SCOPED_TRACE("`swhost1` removed."); EXPECT_STREQ("A,B,C", GetDisplayedCookies(cookies_model.get()).c_str()); @@ -620,9 +659,13 @@ EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); - EXPECT_EQ(57, cookies_model->GetRoot()->GetTotalNodeCount()); + EXPECT_EQ("https://media1/,https://media2/", + GetDisplayedMediaLicenses(cookies_model.get())); + EXPECT_EQ(63, cookies_model->GetRoot()->GetTotalNodeCount()); } - DeleteStoredObjects(cookies_model->GetRoot()->GetChild(17)); + + // sbc2 -> sbcerts -> sbc2 (3 objects) + DeleteStoredObjects(cookies_model->GetRoot()->GetChild(19)); { SCOPED_TRACE("`sbc2` removed."); EXPECT_STREQ("A,B,C", GetDisplayedCookies(cookies_model.get()).c_str()); @@ -643,9 +686,13 @@ EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); - EXPECT_EQ(54, cookies_model->GetRoot()->GetTotalNodeCount()); + EXPECT_EQ("https://media1/,https://media2/", + GetDisplayedMediaLicenses(cookies_model.get())); + EXPECT_EQ(60, cookies_model->GetRoot()->GetTotalNodeCount()); } - DeleteStoredObjects(cookies_model->GetRoot()->GetChild(16)); + + // sbc1 -> sbcerts -> sbc1 (3 objects) + DeleteStoredObjects(cookies_model->GetRoot()->GetChild(18)); { SCOPED_TRACE("`sbc1` removed."); EXPECT_STREQ("A,B,C", GetDisplayedCookies(cookies_model.get()).c_str()); @@ -665,9 +712,13 @@ EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); - EXPECT_EQ(51, cookies_model->GetRoot()->GetTotalNodeCount()); + EXPECT_EQ("https://media1/,https://media2/", + GetDisplayedMediaLicenses(cookies_model.get())); + EXPECT_EQ(57, cookies_model->GetRoot()->GetTotalNodeCount()); } - DeleteStoredObjects(cookies_model->GetRoot()->GetChild(15)); + + // quotahost2 -> quotahost2 (2 objects) + DeleteStoredObjects(cookies_model->GetRoot()->GetChild(17)); { SCOPED_TRACE("`quotahost2` removed."); EXPECT_STREQ("A,B,C", GetDisplayedCookies(cookies_model.get()).c_str()); @@ -686,9 +737,13 @@ EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); - EXPECT_EQ(49, cookies_model->GetRoot()->GetTotalNodeCount()); + EXPECT_EQ("https://media1/,https://media2/", + GetDisplayedMediaLicenses(cookies_model.get())); + EXPECT_EQ(55, cookies_model->GetRoot()->GetTotalNodeCount()); } - DeleteStoredObjects(cookies_model->GetRoot()->GetChild(14)); + + // quotahost1 -> quotahost1 (2 objects) + DeleteStoredObjects(cookies_model->GetRoot()->GetChild(16)); { SCOPED_TRACE("`quotahost1` removed."); EXPECT_STREQ("A,B,C", GetDisplayedCookies(cookies_model.get()).c_str()); @@ -705,8 +760,57 @@ EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("https://media1/,https://media2/", + GetDisplayedMediaLicenses(cookies_model.get())); + EXPECT_EQ(53, cookies_model->GetRoot()->GetTotalNodeCount()); + } + + // media2 -> media_licenses -> media_license (3 objects) + DeleteStoredObjects(cookies_model->GetRoot()->GetChild(15)); + { + SCOPED_TRACE("`media2` removed."); + EXPECT_STREQ("A,B,C", GetDisplayedCookies(cookies_model.get()).c_str()); + EXPECT_EQ("db1,db2", GetDisplayedDatabases(cookies_model.get())); + EXPECT_EQ("http://host1:1/,http://host2:2/", + GetDisplayedLocalStorages(cookies_model.get())); + EXPECT_EQ("http://host1:1/,http://host2:2/", + GetDisplayedSessionStorages(cookies_model.get())); + EXPECT_EQ("http://fshost1:1/,http://fshost2:2/,http://fshost3:3/", + GetDisplayedFileSystems(cookies_model.get())); + EXPECT_EQ("http://idbhost1:1/,http://idbhost2:2/", + GetDisplayedIndexedDBs(cookies_model.get())); + EXPECT_EQ("", GetDisplayedServiceWorkers(cookies_model.get())); + EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", + GetDisplayedCacheStorages(cookies_model.get())); + EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("https://media1/", + GetDisplayedMediaLicenses(cookies_model.get())); + EXPECT_EQ(50, cookies_model->GetRoot()->GetTotalNodeCount()); + } + + // media1 -> media_licenses -> media_license (3 objects) + DeleteStoredObjects(cookies_model->GetRoot()->GetChild(14)); + { + SCOPED_TRACE("`media1` removed."); + EXPECT_STREQ("A,B,C", GetDisplayedCookies(cookies_model.get()).c_str()); + EXPECT_EQ("db1,db2", GetDisplayedDatabases(cookies_model.get())); + EXPECT_EQ("http://host1:1/,http://host2:2/", + GetDisplayedLocalStorages(cookies_model.get())); + EXPECT_EQ("http://host1:1/,http://host2:2/", + GetDisplayedSessionStorages(cookies_model.get())); + EXPECT_EQ("http://fshost1:1/,http://fshost2:2/,http://fshost3:3/", + GetDisplayedFileSystems(cookies_model.get())); + EXPECT_EQ("http://idbhost1:1/,http://idbhost2:2/", + GetDisplayedIndexedDBs(cookies_model.get())); + EXPECT_EQ("", GetDisplayedServiceWorkers(cookies_model.get())); + EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", + GetDisplayedCacheStorages(cookies_model.get())); + EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("", GetDisplayedMediaLicenses(cookies_model.get())); EXPECT_EQ(47, cookies_model->GetRoot()->GetTotalNodeCount()); } + + // idbhost2 -> indexeddb -> http://idbhost2:2/ (3 objects) DeleteStoredObjects(cookies_model->GetRoot()->GetChild(13)); { SCOPED_TRACE("`idbhost2` removed."); @@ -724,8 +828,11 @@ EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("", GetDisplayedMediaLicenses(cookies_model.get())); EXPECT_EQ(44, cookies_model->GetRoot()->GetTotalNodeCount()); } + + // idbhost1 -> indexeddb -> http://idbhost1:1/ (3 objects) DeleteStoredObjects(cookies_model->GetRoot()->GetChild(12)); { SCOPED_TRACE("`idbhost1` removed."); @@ -742,8 +849,12 @@ EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("", GetDisplayedMediaLicenses(cookies_model.get())); EXPECT_EQ(41, cookies_model->GetRoot()->GetTotalNodeCount()); } + + // host2 -> localstorage -> http://host2:2/, + // -> sessionstorage -> http://host2:2/ (5 objects) DeleteStoredObjects(cookies_model->GetRoot()->GetChild(11)); { SCOPED_TRACE("`host2` removed."); @@ -760,8 +871,12 @@ EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("", GetDisplayedMediaLicenses(cookies_model.get())); EXPECT_EQ(36, cookies_model->GetRoot()->GetTotalNodeCount()); } + + // host1 -> localstorage -> http://host1:1/, + // -> sessionstorage -> http://host1:1/ (5 objects) DeleteStoredObjects(cookies_model->GetRoot()->GetChild(10)); { SCOPED_TRACE("`host1` removed."); @@ -776,8 +891,11 @@ EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("", GetDisplayedMediaLicenses(cookies_model.get())); EXPECT_EQ(31, cookies_model->GetRoot()->GetTotalNodeCount()); } + + // gdbhost2 -> database -> db2 (3 objects) DeleteStoredObjects(cookies_model->GetRoot()->GetChild(9)); { SCOPED_TRACE("`gdbhost2` removed."); @@ -792,8 +910,10 @@ EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("", GetDisplayedMediaLicenses(cookies_model.get())); EXPECT_EQ(28, cookies_model->GetRoot()->GetTotalNodeCount()); } + // gdbhost1 -> database -> db1 (3 objects) DeleteStoredObjects(cookies_model->GetRoot()->GetChild(8)); { SCOPED_TRACE("`gdbhost1` removed."); @@ -808,8 +928,11 @@ EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("", GetDisplayedMediaLicenses(cookies_model.get())); EXPECT_EQ(25, cookies_model->GetRoot()->GetTotalNodeCount()); } + + // fshost3 -> filesystem -> http://fshost3:1/ (3 objects) DeleteStoredObjects(cookies_model->GetRoot()->GetChild(7)); { SCOPED_TRACE("`fshost3` removed."); @@ -824,8 +947,11 @@ EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("", GetDisplayedMediaLicenses(cookies_model.get())); EXPECT_EQ(22, cookies_model->GetRoot()->GetTotalNodeCount()); } + + // fshost2 -> filesystem -> http://fshost2:1/ (3 objects) DeleteStoredObjects(cookies_model->GetRoot()->GetChild(6)); { SCOPED_TRACE("`fshost2` removed."); @@ -840,8 +966,11 @@ EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("", GetDisplayedMediaLicenses(cookies_model.get())); EXPECT_EQ(19, cookies_model->GetRoot()->GetTotalNodeCount()); } + + // fshost1 -> filesystem -> http://fshost1:1/ (3 objects) DeleteStoredObjects(cookies_model->GetRoot()->GetChild(5)); { SCOPED_TRACE("`fshost1` removed."); @@ -855,8 +984,11 @@ EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("", GetDisplayedMediaLicenses(cookies_model.get())); EXPECT_EQ(16, cookies_model->GetRoot()->GetTotalNodeCount()); } + + // foo3 -> cookies -> c (3 objects) DeleteStoredObjects(cookies_model->GetRoot()->GetChild(4)); { SCOPED_TRACE("`foo3` removed."); @@ -870,8 +1002,11 @@ EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("", GetDisplayedMediaLicenses(cookies_model.get())); EXPECT_EQ(13, cookies_model->GetRoot()->GetTotalNodeCount()); } + + // foo2 -> cookies -> b (3 objects) DeleteStoredObjects(cookies_model->GetRoot()->GetChild(3)); { SCOPED_TRACE("`foo2` removed."); @@ -885,8 +1020,11 @@ EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("", GetDisplayedMediaLicenses(cookies_model.get())); EXPECT_EQ(10, cookies_model->GetRoot()->GetTotalNodeCount()); } + + // foo1 -> cookies -> a (3 objects) DeleteStoredObjects(cookies_model->GetRoot()->GetChild(2)); { SCOPED_TRACE("`foo1` removed."); @@ -900,8 +1038,11 @@ EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("", GetDisplayedMediaLicenses(cookies_model.get())); EXPECT_EQ(7, cookies_model->GetRoot()->GetTotalNodeCount()); } + + // cshost2 -> cache storage -> https://cshost2:2/ (3 objects) DeleteStoredObjects(cookies_model->GetRoot()->GetChild(1)); { SCOPED_TRACE("`cshost2` removed."); @@ -915,8 +1056,11 @@ EXPECT_EQ("https://cshost1:1/", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("", GetDisplayedMediaLicenses(cookies_model.get())); EXPECT_EQ(4, cookies_model->GetRoot()->GetTotalNodeCount()); } + + // cshost1 -> cache storage -> https://cshost1:1/ (3 objects) DeleteStoredObjects(cookies_model->GetRoot()->GetChild(0)); { SCOPED_TRACE("`cshost1` removed."); @@ -929,6 +1073,7 @@ EXPECT_EQ("", GetDisplayedServiceWorkers(cookies_model.get())); EXPECT_EQ("", GetDisplayedCacheStorages(cookies_model.get())); EXPECT_EQ("", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("", GetDisplayedMediaLicenses(cookies_model.get())); EXPECT_EQ(1, cookies_model->GetRoot()->GetTotalNodeCount()); } } @@ -941,9 +1086,9 @@ { SCOPED_TRACE("First cookies origin removed"); EXPECT_STREQ("B,C", GetDisplayedCookies(cookies_model.get()).c_str()); - // 63 because in this case, the origin remains, although the COOKIES + // 69 because in this case, the origin remains, although the COOKIES // node beneath it has been deleted. - EXPECT_EQ(63, cookies_model->GetRoot()->GetTotalNodeCount()); + EXPECT_EQ(69, cookies_model->GetRoot()->GetTotalNodeCount()); EXPECT_EQ("db1,db2", GetDisplayedDatabases(cookies_model.get())); EXPECT_EQ("http://host1:1/,http://host2:2/", GetDisplayedLocalStorages(cookies_model.get())); @@ -959,6 +1104,9 @@ GetDisplayedServiceWorkers(cookies_model.get())); EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); + EXPECT_EQ("xyz.com", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("https://media1/,https://media2/", + GetDisplayedMediaLicenses(cookies_model.get())); } DeleteStoredObjects(cookies_model->GetRoot()->GetChild(8)->GetChild(0)); @@ -980,7 +1128,10 @@ GetDisplayedServiceWorkers(cookies_model.get())); EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); - EXPECT_EQ(61, cookies_model->GetRoot()->GetTotalNodeCount()); + EXPECT_EQ("xyz.com", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("https://media1/,https://media2/", + GetDisplayedMediaLicenses(cookies_model.get())); + EXPECT_EQ(67, cookies_model->GetRoot()->GetTotalNodeCount()); } DeleteStoredObjects(cookies_model->GetRoot()->GetChild(10)->GetChild(0)); @@ -1002,7 +1153,10 @@ GetDisplayedServiceWorkers(cookies_model.get())); EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); - EXPECT_EQ(59, cookies_model->GetRoot()->GetTotalNodeCount()); + EXPECT_EQ("xyz.com", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("https://media1/,https://media2/", + GetDisplayedMediaLicenses(cookies_model.get())); + EXPECT_EQ(65, cookies_model->GetRoot()->GetTotalNodeCount()); } } @@ -1029,9 +1183,12 @@ GetDisplayedServiceWorkers(cookies_model.get())); EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); - // 63 because in this case, the origin remains, although the COOKIES + EXPECT_EQ("xyz.com", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("https://media1/,https://media2/", + GetDisplayedMediaLicenses(cookies_model.get())); + // 69 because in this case, the origin remains, although the COOKIES // node beneath it has been deleted. - EXPECT_EQ(63, cookies_model->GetRoot()->GetTotalNodeCount()); + EXPECT_EQ(69, cookies_model->GetRoot()->GetTotalNodeCount()); } DeleteStoredObjects(cookies_model->GetRoot()->GetChild(8)->GetChild(0)); @@ -1053,7 +1210,10 @@ GetDisplayedServiceWorkers(cookies_model.get())); EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); - EXPECT_EQ(61, cookies_model->GetRoot()->GetTotalNodeCount()); + EXPECT_EQ("xyz.com", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("https://media1/,https://media2/", + GetDisplayedMediaLicenses(cookies_model.get())); + EXPECT_EQ(67, cookies_model->GetRoot()->GetTotalNodeCount()); } DeleteStoredObjects(cookies_model->GetRoot()->GetChild(10)->GetChild(0)); @@ -1075,7 +1235,10 @@ GetDisplayedServiceWorkers(cookies_model.get())); EXPECT_EQ("https://cshost1:1/,https://cshost2:2/", GetDisplayedCacheStorages(cookies_model.get())); - EXPECT_EQ(59, cookies_model->GetRoot()->GetTotalNodeCount()); + EXPECT_EQ("xyz.com", GetDisplayedFlashLSOs(cookies_model.get())); + EXPECT_EQ("https://media1/,https://media2/", + GetDisplayedMediaLicenses(cookies_model.get())); + EXPECT_EQ(65, cookies_model->GetRoot()->GetTotalNodeCount()); } } @@ -1092,7 +1255,8 @@ mock_browsing_data_channel_id_helper_, mock_browsing_data_service_worker_helper_, mock_browsing_data_cache_storage_helper_, - mock_browsing_data_flash_lso_helper_); + mock_browsing_data_flash_lso_helper_, + mock_browsing_data_media_license_helper_); CookiesTreeModel cookies_model(container, special_storage_policy()); mock_browsing_data_cookie_helper_-> @@ -1199,7 +1363,8 @@ mock_browsing_data_channel_id_helper_, mock_browsing_data_service_worker_helper_, mock_browsing_data_cache_storage_helper_, - mock_browsing_data_flash_lso_helper_); + mock_browsing_data_flash_lso_helper_, + mock_browsing_data_media_license_helper_); CookiesTreeModel cookies_model(container, special_storage_policy()); mock_browsing_data_cookie_helper_-> @@ -1309,7 +1474,8 @@ mock_browsing_data_channel_id_helper_, mock_browsing_data_service_worker_helper_, mock_browsing_data_cache_storage_helper_, - mock_browsing_data_flash_lso_helper_); + mock_browsing_data_flash_lso_helper_, + mock_browsing_data_media_license_helper_); CookiesTreeModel cookies_model(container, special_storage_policy()); mock_browsing_data_cookie_helper_-> @@ -1353,7 +1519,8 @@ mock_browsing_data_channel_id_helper_, mock_browsing_data_service_worker_helper_, mock_browsing_data_cache_storage_helper_, - mock_browsing_data_flash_lso_helper_); + mock_browsing_data_flash_lso_helper_, + mock_browsing_data_media_license_helper_); CookiesTreeModel cookies_model(container, special_storage_policy()); mock_browsing_data_cookie_helper_-> @@ -1402,7 +1569,8 @@ mock_browsing_data_channel_id_helper_, mock_browsing_data_service_worker_helper_, mock_browsing_data_cache_storage_helper_, - mock_browsing_data_flash_lso_helper_); + mock_browsing_data_flash_lso_helper_, + mock_browsing_data_media_license_helper_); CookiesTreeModel cookies_model(container, special_storage_policy()); mock_browsing_data_cookie_helper_->AddCookieSamples(host, "A=1"); @@ -1507,7 +1675,8 @@ mock_browsing_data_channel_id_helper_, mock_browsing_data_service_worker_helper_, mock_browsing_data_cache_storage_helper_, - mock_browsing_data_flash_lso_helper_); + mock_browsing_data_flash_lso_helper_, + mock_browsing_data_media_license_helper_); CookiesTreeModel cookies_model(container, special_storage_policy()); mock_browsing_data_cookie_helper_-> @@ -1549,7 +1718,8 @@ mock_browsing_data_channel_id_helper_, mock_browsing_data_service_worker_helper_, mock_browsing_data_cache_storage_helper_, - mock_browsing_data_flash_lso_helper_); + mock_browsing_data_flash_lso_helper_, + mock_browsing_data_media_license_helper_); CookiesTreeModel cookies_model(container, special_storage_policy()); mock_browsing_data_cookie_helper_->AddCookieSamples( @@ -1637,7 +1807,8 @@ mock_browsing_data_channel_id_helper_, mock_browsing_data_service_worker_helper_, mock_browsing_data_cache_storage_helper_, - mock_browsing_data_flash_lso_helper_); + mock_browsing_data_flash_lso_helper_, + mock_browsing_data_media_license_helper_); CookiesTreeModel cookies_model(container, special_storage_policy()); mock_browsing_data_cookie_helper_-> @@ -1648,18 +1819,19 @@ TEST_F(CookiesTreeModelTest, Suborigins) { LocalDataContainer* container = - new LocalDataContainer(mock_browsing_data_cookie_helper_.get(), - mock_browsing_data_database_helper_.get(), - mock_browsing_data_local_storage_helper_.get(), - mock_browsing_data_session_storage_helper_.get(), - mock_browsing_data_appcache_helper_.get(), - mock_browsing_data_indexed_db_helper_.get(), - mock_browsing_data_file_system_helper_.get(), - mock_browsing_data_quota_helper_.get(), - mock_browsing_data_channel_id_helper_.get(), - mock_browsing_data_service_worker_helper_.get(), - mock_browsing_data_cache_storage_helper_.get(), - mock_browsing_data_flash_lso_helper_.get()); + new LocalDataContainer(mock_browsing_data_cookie_helper_, + mock_browsing_data_database_helper_, + mock_browsing_data_local_storage_helper_, + mock_browsing_data_session_storage_helper_, + mock_browsing_data_appcache_helper_, + mock_browsing_data_indexed_db_helper_, + mock_browsing_data_file_system_helper_, + mock_browsing_data_quota_helper_, + mock_browsing_data_channel_id_helper_, + mock_browsing_data_service_worker_helper_, + mock_browsing_data_cache_storage_helper_, + mock_browsing_data_flash_lso_helper_, + mock_browsing_data_media_license_helper_); CookiesTreeModel cookies_model(container, special_storage_policy()); mock_browsing_data_local_storage_helper_
diff --git a/chrome/browser/browsing_data/local_data_container.cc b/chrome/browser/browsing_data/local_data_container.cc index 395c329..00a4fdc 100644 --- a/chrome/browser/browsing_data/local_data_container.cc +++ b/chrome/browser/browsing_data/local_data_container.cc
@@ -26,7 +26,8 @@ scoped_refptr<BrowsingDataChannelIDHelper> channel_id_helper, scoped_refptr<BrowsingDataServiceWorkerHelper> service_worker_helper, scoped_refptr<BrowsingDataCacheStorageHelper> cache_storage_helper, - scoped_refptr<BrowsingDataFlashLSOHelper> flash_lso_helper) + scoped_refptr<BrowsingDataFlashLSOHelper> flash_lso_helper, + scoped_refptr<BrowsingDataMediaLicenseHelper> media_license_helper) : appcache_helper_(std::move(appcache_helper)), cookie_helper_(std::move(cookie_helper)), database_helper_(std::move(database_helper)), @@ -39,6 +40,7 @@ service_worker_helper_(std::move(service_worker_helper)), cache_storage_helper_(std::move(cache_storage_helper)), flash_lso_helper_(std::move(flash_lso_helper)), + media_license_helper_(std::move(media_license_helper)), weak_ptr_factory_(this) {} LocalDataContainer::~LocalDataContainer() {} @@ -132,6 +134,13 @@ weak_ptr_factory_.GetWeakPtr())); } + if (media_license_helper_.get()) { + batches_started_++; + media_license_helper_->StartFetching( + base::Bind(&LocalDataContainer::OnMediaLicenseInfoLoaded, + weak_ptr_factory_.GetWeakPtr())); + } + model_->SetBatchExpectation(batches_started_, true); } @@ -234,3 +243,10 @@ DCHECK(model_); model_->PopulateFlashLSOInfo(this); } + +void LocalDataContainer::OnMediaLicenseInfoLoaded( + const MediaLicenseInfoList& media_license_info) { + media_license_info_list_ = media_license_info; + DCHECK(model_); + model_->PopulateMediaLicenseInfo(this); +}
diff --git a/chrome/browser/browsing_data/local_data_container.h b/chrome/browser/browsing_data/local_data_container.h index de2b923..5cbf450e6 100644 --- a/chrome/browser/browsing_data/local_data_container.h +++ b/chrome/browser/browsing_data/local_data_container.h
@@ -22,6 +22,7 @@ #include "chrome/browser/browsing_data/browsing_data_file_system_helper.h" #include "chrome/browser/browsing_data/browsing_data_indexed_db_helper.h" #include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h" +#include "chrome/browser/browsing_data/browsing_data_media_license_helper.h" #include "chrome/browser/browsing_data/browsing_data_quota_helper.h" #include "chrome/browser/browsing_data/browsing_data_service_worker_helper.h" #include "net/ssl/channel_id_store.h" @@ -53,6 +54,8 @@ typedef std::list<content::CacheStorageUsageInfo> CacheStorageUsageInfoList; typedef std::map<GURL, std::list<content::AppCacheInfo> > AppCacheInfoMap; typedef std::vector<std::string> FlashLSODomainList; +typedef std::list<BrowsingDataMediaLicenseHelper::MediaLicenseInfo> + MediaLicenseInfoList; } // namespace @@ -76,7 +79,8 @@ scoped_refptr<BrowsingDataChannelIDHelper> channel_id_helper, scoped_refptr<BrowsingDataServiceWorkerHelper> service_worker_helper, scoped_refptr<BrowsingDataCacheStorageHelper> cache_storage_helper, - scoped_refptr<BrowsingDataFlashLSOHelper> flash_data_helper); + scoped_refptr<BrowsingDataFlashLSOHelper> flash_data_helper, + scoped_refptr<BrowsingDataMediaLicenseHelper> media_license_helper); virtual ~LocalDataContainer(); // This method must be called to start the process of fetching the resources. @@ -86,6 +90,7 @@ private: friend class CookiesTreeModel; friend class CookieTreeAppCacheNode; + friend class CookieTreeMediaLicenseNode; friend class CookieTreeCookieNode; friend class CookieTreeDatabaseNode; friend class CookieTreeLocalStorageNode; @@ -118,6 +123,7 @@ void OnCacheStorageModelInfoLoaded( const CacheStorageUsageInfoList& cache_storage_info); void OnFlashLSOInfoLoaded(const FlashLSODomainList& domains); + void OnMediaLicenseInfoLoaded(const MediaLicenseInfoList& media_license_info); // Pointers to the helper objects, needed to retreive all the types of locally // stored data. @@ -133,6 +139,7 @@ scoped_refptr<BrowsingDataServiceWorkerHelper> service_worker_helper_; scoped_refptr<BrowsingDataCacheStorageHelper> cache_storage_helper_; scoped_refptr<BrowsingDataFlashLSOHelper> flash_lso_helper_; + scoped_refptr<BrowsingDataMediaLicenseHelper> media_license_helper_; // Storage for all the data that was retrieved through the helper objects. // The collected data is used for (re)creating the CookiesTreeModel. @@ -148,6 +155,7 @@ ServiceWorkerUsageInfoList service_worker_info_list_; CacheStorageUsageInfoList cache_storage_info_list_; FlashLSODomainList flash_lso_domain_list_; + MediaLicenseInfoList media_license_info_list_; // A delegate, which must outlive this object. The update callbacks use the // delegate to deliver the updated data to the CookieTreeModel.
diff --git a/chrome/browser/browsing_data/mock_browsing_data_media_license_helper.cc b/chrome/browser/browsing_data/mock_browsing_data_media_license_helper.cc new file mode 100644 index 0000000..48e887fb --- /dev/null +++ b/chrome/browser/browsing_data/mock_browsing_data_media_license_helper.cc
@@ -0,0 +1,52 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/browsing_data/mock_browsing_data_media_license_helper.h" + +#include <algorithm> + +#include "testing/gtest/include/gtest/gtest.h" + +MockBrowsingDataMediaLicenseHelper::MockBrowsingDataMediaLicenseHelper( + Profile* profile) {} + +MockBrowsingDataMediaLicenseHelper::~MockBrowsingDataMediaLicenseHelper() {} + +void MockBrowsingDataMediaLicenseHelper::StartFetching( + const FetchCallback& callback) { + ASSERT_FALSE(callback.is_null()); + ASSERT_TRUE(callback_.is_null()); + callback_ = callback; +} + +void MockBrowsingDataMediaLicenseHelper::DeleteMediaLicenseOrigin( + const GURL& origin) { + auto entry = std::find_if(media_licenses_.begin(), media_licenses_.end(), + [origin](const MediaLicenseInfo& entry) { + return entry.origin == origin; + }); + ASSERT_TRUE(entry != media_licenses_.end()); + media_licenses_.erase(entry); +} + +void MockBrowsingDataMediaLicenseHelper::AddMediaLicenseSamples() { + const GURL kOrigin1("https://media1/"); + const GURL kOrigin2("https://media2/"); + const base::Time ten_days_ago = + base::Time::Now() - base::TimeDelta::FromDays(10); + const base::Time twenty_days_ago = + base::Time::Now() - base::TimeDelta::FromDays(20); + + media_licenses_.push_back(MediaLicenseInfo(kOrigin1, 1000, ten_days_ago)); + media_licenses_.push_back(MediaLicenseInfo(kOrigin2, 50, twenty_days_ago)); +} + +void MockBrowsingDataMediaLicenseHelper::Notify() { + callback_.Run(media_licenses_); + callback_ = FetchCallback(); +} + +bool MockBrowsingDataMediaLicenseHelper::AllDeleted() { + return media_licenses_.empty(); +}
diff --git a/chrome/browser/browsing_data/mock_browsing_data_media_license_helper.h b/chrome/browser/browsing_data/mock_browsing_data_media_license_helper.h new file mode 100644 index 0000000..206864c --- /dev/null +++ b/chrome/browser/browsing_data/mock_browsing_data_media_license_helper.h
@@ -0,0 +1,46 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_BROWSING_DATA_MOCK_BROWSING_DATA_MEDIA_LICENSE_HELPER_H_ +#define CHROME_BROWSER_BROWSING_DATA_MOCK_BROWSING_DATA_MEDIA_LICENSE_HELPER_H_ + +#include <stdint.h> +#include <list> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/time/time.h" +#include "chrome/browser/browsing_data/browsing_data_media_license_helper.h" +#include "chrome/browser/profiles/profile.h" +#include "url/gurl.h" + +class MockBrowsingDataMediaLicenseHelper + : public BrowsingDataMediaLicenseHelper { + public: + explicit MockBrowsingDataMediaLicenseHelper(Profile* profile); + + // BrowsingDataMediaLicenseHelper implementation: + void StartFetching(const FetchCallback& callback) override; + void DeleteMediaLicenseOrigin(const GURL& origin) override; + + // Add some MediaLicenseInfo samples. + void AddMediaLicenseSamples(); + + // Notifies the callback. + void Notify(); + + // Returns true if the origin list is empty. + bool AllDeleted(); + + protected: + ~MockBrowsingDataMediaLicenseHelper() override; + + private: + FetchCallback callback_; + std::list<MediaLicenseInfo> media_licenses_; + + DISALLOW_COPY_AND_ASSIGN(MockBrowsingDataMediaLicenseHelper); +}; + +#endif // CHROME_BROWSER_BROWSING_DATA_MOCK_BROWSING_DATA_MEDIA_LICENSE_HELPER_H_
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index dd7abdb..dd1a1e2e 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -51,6 +51,7 @@ #include "chrome/browser/engagement/site_engagement_eviction_policy.h" #include "chrome/browser/font_family_cache.h" #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h" +#include "chrome/browser/memory/chrome_memory_coordinator_delegate.h" #include "chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.h" #include "chrome/browser/nacl_host/nacl_browser_delegate_impl.h" #include "chrome/browser/notifications/platform_notification_service_impl.h" @@ -3246,3 +3247,8 @@ } } #endif // defined(ENABLE_WEBRTC) + +std::unique_ptr<content::MemoryCoordinatorDelegate> +ChromeContentBrowserClient::GetMemoryCoordinatorDelegate() { + return memory::ChromeMemoryCoordinatorDelegate::Create(); +}
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index b1f2989d..9b157ec 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -305,6 +305,8 @@ content::NavigationHandle* handle) override; std::unique_ptr<content::NavigationUIData> GetNavigationUIData( content::NavigationHandle* navigation_handle) override; + std::unique_ptr<content::MemoryCoordinatorDelegate> + GetMemoryCoordinatorDelegate() override; private: friend class DisableWebRtcEncryptionFlagTest;
diff --git a/chrome/browser/chrome_device_client.h b/chrome/browser/chrome_device_client.h index aa6635efb..a4ed096d 100644 --- a/chrome/browser/chrome_device_client.h +++ b/chrome/browser/chrome_device_client.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_CHROME_DEVICE_CLIENT_H_ #define CHROME_BROWSER_CHROME_DEVICE_CLIENT_H_ -#include "device/core/device_client.h" +#include "device/base/device_client.h" #include <memory>
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc b/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc index 147172f..faefe56 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc +++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc
@@ -578,14 +578,13 @@ } void KioskAppManager::OnKioskAppCacheUpdated(const std::string& app_id) { - FOR_EACH_OBSERVER( - KioskAppManagerObserver, observers_, OnKioskAppCacheUpdated(app_id)); + for (auto& observer : observers_) + observer.OnKioskAppCacheUpdated(app_id); } void KioskAppManager::OnKioskAppExternalUpdateComplete(bool success) { - FOR_EACH_OBSERVER(KioskAppManagerObserver, - observers_, - OnKioskAppExternalUpdateComplete(success)); + for (auto& observer : observers_) + observer.OnKioskAppExternalUpdateComplete(success); } void KioskAppManager::PutValidatedExternalExtension( @@ -744,8 +743,8 @@ UpdateExternalCachePrefs(); RetryFailedAppDataFetch(); - FOR_EACH_OBSERVER(KioskAppManagerObserver, observers_, - OnKioskAppsSettingsChanged()); + for (auto& observer : observers_) + observer.OnKioskAppsSettingsChanged(); } void KioskAppManager::ClearRemovedApps( @@ -805,15 +804,13 @@ } void KioskAppManager::OnKioskAppDataChanged(const std::string& app_id) { - FOR_EACH_OBSERVER(KioskAppManagerObserver, - observers_, - OnKioskAppDataChanged(app_id)); + for (auto& observer : observers_) + observer.OnKioskAppDataChanged(app_id); } void KioskAppManager::OnKioskAppDataLoadFailure(const std::string& app_id) { - FOR_EACH_OBSERVER(KioskAppManagerObserver, - observers_, - OnKioskAppDataLoadFailure(app_id)); + for (auto& observer : observers_) + observer.OnKioskAppDataLoadFailure(app_id); } void KioskAppManager::OnExtensionListsUpdated( @@ -830,10 +827,8 @@ if (GetCachedCrx(id, &crx_path, &version)) app_data->SetCachedCrx(crx_path); - FOR_EACH_OBSERVER(KioskAppManagerObserver, - observers_, - OnKioskExtensionLoadedInCache(id)); - + for (auto& observer : observers_) + observer.OnKioskExtensionLoadedInCache(id); } void KioskAppManager::OnExtensionDownloadFailed( @@ -842,9 +837,8 @@ KioskAppData* app_data = GetAppDataMutable(id); if (!app_data) return; - FOR_EACH_OBSERVER(KioskAppManagerObserver, - observers_, - OnKioskExtensionDownloadFailed(id)); + for (auto& observer : observers_) + observer.OnKioskExtensionDownloadFailed(id); } KioskAppManager::AutoLoginState KioskAppManager::GetAutoLoginState() const {
diff --git a/chrome/browser/chromeos/arc/arc_auth_code_fetcher_delegate.h b/chrome/browser/chromeos/arc/arc_auth_code_fetcher_delegate.h index f5af93a0..412efb6 100644 --- a/chrome/browser/chromeos/arc/arc_auth_code_fetcher_delegate.h +++ b/chrome/browser/chromeos/arc/arc_auth_code_fetcher_delegate.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_CHROMEOS_ARC_ARC_AUTH_CODE_FETCHER_DELEGATE_H_ #define CHROME_BROWSER_CHROMEOS_ARC_ARC_AUTH_CODE_FETCHER_DELEGATE_H_ +#include <string> + namespace arc { class ArcAuthCodeFetcherDelegate {
diff --git a/chrome/browser/chromeos/arc/arc_auth_service.cc b/chrome/browser/chromeos/arc/arc_auth_service.cc index 3217516..a5e68069 100644 --- a/chrome/browser/chromeos/arc/arc_auth_service.cc +++ b/chrome/browser/chromeos/arc/arc_auth_service.cc
@@ -97,8 +97,8 @@ } ProvisioningResult ConvertArcSignInFailureReasonToProvisioningResult( - arc::mojom::ArcSignInFailureReason reason) { - using ArcSignInFailureReason = arc::mojom::ArcSignInFailureReason; + mojom::ArcSignInFailureReason reason) { + using ArcSignInFailureReason = mojom::ArcSignInFailureReason; #define MAP_PROVISIONING_RESULT(name) \ case ArcSignInFailureReason::name: \ @@ -361,7 +361,7 @@ observer.OnInitialStart(); } -void ArcAuthService::OnSignInFailed(arc::mojom::ArcSignInFailureReason reason) { +void ArcAuthService::OnSignInFailed(mojom::ArcSignInFailureReason reason) { OnSignInFailedInternal( ConvertArcSignInFailureReasonToProvisioningResult(reason)); }
diff --git a/chrome/browser/chromeos/arc/arc_auth_service.h b/chrome/browser/chromeos/arc/arc_auth_service.h index bef5aa4e..e4aca45 100644 --- a/chrome/browser/chromeos/arc/arc_auth_service.h +++ b/chrome/browser/chromeos/arc/arc_auth_service.h
@@ -147,7 +147,7 @@ void GetAuthCodeAndAccountType( const GetAuthCodeAndAccountTypeCallback& callback) override; void OnSignInComplete() override; - void OnSignInFailed(arc::mojom::ArcSignInFailureReason reason) override; + void OnSignInFailed(mojom::ArcSignInFailureReason reason) override; // Callback is called with a bool that indicates the management status of the // user. void GetIsAccountManaged(
diff --git a/chrome/browser/chromeos/arc/arc_downloads_watcher_service.cc b/chrome/browser/chromeos/arc/arc_downloads_watcher_service.cc index 58b436b..fe2b98a4 100644 --- a/chrome/browser/chromeos/arc/arc_downloads_watcher_service.cc +++ b/chrome/browser/chromeos/arc/arc_downloads_watcher_service.cc
@@ -10,7 +10,9 @@ #include <iterator> #include <map> #include <memory> +#include <string> #include <utility> +#include <vector> #include "base/callback.h" #include "base/files/file_enumerator.h" @@ -24,7 +26,6 @@ #include "chrome/common/chrome_paths.h" #include "components/arc/arc_bridge_service.h" #include "content/public/browser/browser_thread.h" -#include "mojo/public/cpp/bindings/array.h" using content::BrowserThread;
diff --git a/chrome/browser/chromeos/arc/arc_downloads_watcher_service.h b/chrome/browser/chromeos/arc/arc_downloads_watcher_service.h index d469f71..eabc575 100644 --- a/chrome/browser/chromeos/arc/arc_downloads_watcher_service.h +++ b/chrome/browser/chromeos/arc/arc_downloads_watcher_service.h
@@ -6,20 +6,23 @@ #define CHROME_BROWSER_CHROMEOS_ARC_ARC_DOWNLOADS_WATCHER_SERVICE_H_ #include <memory> -#include <vector> #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/common/file_system.mojom.h" #include "components/arc/instance_holder.h" +#include "mojo/public/cpp/bindings/array.h" +#include "mojo/public/cpp/bindings/string.h" namespace base { class FilePath; -} +} // namespace base namespace arc { +class ArcBridgeService; + // Returns true if the file path has a media extension supported by Android. bool HasAndroidSupportedMediaExtension(const base::FilePath& path);
diff --git a/chrome/browser/chromeos/arc/arc_enterprise_reporting_service.cc b/chrome/browser/chromeos/arc/arc_enterprise_reporting_service.cc index 7b69da2..f4ff3ab 100644 --- a/chrome/browser/chromeos/arc/arc_enterprise_reporting_service.cc +++ b/chrome/browser/chromeos/arc/arc_enterprise_reporting_service.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/logging.h" #include "chrome/browser/chromeos/arc/arc_auth_service.h" +#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service_manager.h" #include "components/arc/user_data/arc_user_data_service.h" @@ -40,7 +41,7 @@ VLOG(1) << "ReportManagementState state=" << state; if (state == mojom::ManagementState::MANAGED_DO_LOST) { - DCHECK(arc::ArcServiceManager::Get()); + DCHECK(ArcServiceManager::Get()); ArcAuthService::Get()->RemoveArcData(); ArcAuthService::Get()->StopAndEnableArc(); }
diff --git a/chrome/browser/chromeos/arc/arc_enterprise_reporting_service.h b/chrome/browser/chromeos/arc/arc_enterprise_reporting_service.h index 35f8ca3..5893ce9 100644 --- a/chrome/browser/chromeos/arc/arc_enterprise_reporting_service.h +++ b/chrome/browser/chromeos/arc/arc_enterprise_reporting_service.h
@@ -10,13 +10,15 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/common/enterprise_reporting.mojom.h" #include "components/arc/instance_holder.h" #include "mojo/public/cpp/bindings/binding.h" namespace arc { +class ArcBridgeService; + // This class controls the ARC enterprise reporting. class ArcEnterpriseReportingService : public ArcService,
diff --git a/chrome/browser/chromeos/arc/arc_policy_bridge.cc b/chrome/browser/chromeos/arc/arc_policy_bridge.cc index cc2cb8ae..3b0784c0 100644 --- a/chrome/browser/chromeos/arc/arc_policy_bridge.cc +++ b/chrome/browser/chromeos/arc/arc_policy_bridge.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/policy/profile_policy_connector.h" #include "chrome/browser/policy/profile_policy_connector_factory.h" #include "chromeos/network/onc/onc_utils.h" +#include "components/arc/arc_bridge_service.h" #include "components/onc/onc_constants.h" #include "components/policy/core/common/policy_map.h" #include "components/policy/core/common/policy_namespace.h" @@ -174,7 +175,7 @@ base::DictionaryValue data; data.SetString("X509", x509_data); - ca_certs->Append(data.DeepCopy()); + ca_certs->Append(data.CreateDeepCopy()); } filtered_policies->Set(kArcCaCerts, std::move(ca_certs)); }
diff --git a/chrome/browser/chromeos/arc/arc_policy_bridge.h b/chrome/browser/chromeos/arc/arc_policy_bridge.h index b26697e..b7bfda1 100644 --- a/chrome/browser/chromeos/arc/arc_policy_bridge.h +++ b/chrome/browser/chromeos/arc/arc_policy_bridge.h
@@ -6,8 +6,8 @@ #define CHROME_BROWSER_CHROMEOS_ARC_ARC_POLICY_BRIDGE_H_ #include "base/macros.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/common/policy.mojom.h" #include "components/arc/instance_holder.h" #include "components/policy/core/common/policy_service.h" #include "mojo/public/cpp/bindings/binding.h" @@ -18,6 +18,8 @@ namespace arc { +class ArcBridgeService; + // Constants for the ARC certs sync mode are defined in the policy, please keep // its in sync. enum ArcCertsSyncMode : int32_t {
diff --git a/chrome/browser/chromeos/arc/arc_policy_bridge_unittest.cc b/chrome/browser/chromeos/arc/arc_policy_bridge_unittest.cc index de5e9d5..ff0afe98 100644 --- a/chrome/browser/chromeos/arc/arc_policy_bridge_unittest.cc +++ b/chrome/browser/chromeos/arc/arc_policy_bridge_unittest.cc
@@ -118,12 +118,12 @@ // Not an unused variable. Unit tests do not have a message loop by themselves // and mojo needs a message loop for communication. base::MessageLoop loop_; - std::unique_ptr<arc::FakeArcBridgeService> bridge_service_; - std::unique_ptr<arc::ArcPolicyBridge> policy_bridge_; + std::unique_ptr<FakeArcBridgeService> bridge_service_; + std::unique_ptr<ArcPolicyBridge> policy_bridge_; // Always keep policy_instance_ below bridge_service_, so that // policy_instance_ is destructed first. It needs to remove itself as // observer. - std::unique_ptr<arc::FakePolicyInstance> policy_instance_; + std::unique_ptr<FakePolicyInstance> policy_instance_; policy::PolicyMap policy_map_; policy::MockPolicyService policy_service_;
diff --git a/chrome/browser/chromeos/arc/arc_print_service.h b/chrome/browser/chromeos/arc/arc_print_service.h index b798f0c2..969572ee 100644 --- a/chrome/browser/chromeos/arc/arc_print_service.h +++ b/chrome/browser/chromeos/arc/arc_print_service.h
@@ -6,12 +6,15 @@ #define CHROME_BROWSER_CHROMEOS_ARC_ARC_PRINT_SERVICE_H_ #include "base/macros.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/common/print.mojom.h" +#include "components/arc/instance_holder.h" #include "mojo/public/cpp/bindings/binding.h" namespace arc { +class ArcBridgeService; + class ArcPrintService : public ArcService, public InstanceHolder<mojom::PrintInstance>::Observer, public mojom::PrintHost {
diff --git a/chrome/browser/chromeos/arc/arc_process_service.cc b/chrome/browser/chromeos/arc/arc_process_service.cc index c08d34e..4763810 100644 --- a/chrome/browser/chromeos/arc/arc_process_service.cc +++ b/chrome/browser/chromeos/arc/arc_process_service.cc
@@ -22,6 +22,7 @@ #include "base/process/process_iterator.h" #include "base/task_runner_util.h" #include "base/trace_event/trace_event.h" +#include "components/arc/arc_bridge_service.h" #include "content/public/browser/browser_thread.h" namespace arc { @@ -57,8 +58,8 @@ return base::kNullProcessId; } -std::vector<arc::ArcProcess> GetArcSystemProcessList() { - std::vector<arc::ArcProcess> ret_processes; +std::vector<ArcProcess> GetArcSystemProcessList() { + std::vector<ArcProcess> ret_processes; const base::ProcessIterator::ProcessEntries& entry_list = base::ProcessIterator(nullptr).Snapshot(); const base::ProcessId arc_init_pid = GetArcInitProcessId(entry_list); @@ -140,7 +141,7 @@ std::vector<ArcProcess> FilterProcessList( const ArcProcessService::NSPidToPidMap& pid_map, - mojo::Array<arc::mojom::RunningAppProcessInfoPtr> processes) { + mojo::Array<mojom::RunningAppProcessInfoPtr> processes) { std::vector<ArcProcess> ret_processes; for (const auto& entry : processes) { const auto it = pid_map.find(entry->pid); @@ -167,7 +168,7 @@ std::vector<ArcProcess> UpdateAndReturnProcessList( scoped_refptr<ArcProcessService::NSPidToPidMap> nspid_map, - mojo::Array<arc::mojom::RunningAppProcessInfoPtr> processes) { + mojo::Array<mojom::RunningAppProcessInfoPtr> processes) { ArcProcessService::NSPidToPidMap& pid_map = *nspid_map; // Cleanup dead pids in the cache |pid_map|. std::unordered_set<ProcessId> nspid_to_remove; @@ -244,7 +245,7 @@ RequestProcessListCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - arc::mojom::ProcessInstance* process_instance = + mojom::ProcessInstance* process_instance = arc_bridge_service()->process()->GetInstanceForMethod( "RequestProcessList"); if (!process_instance) { @@ -258,7 +259,7 @@ void ArcProcessService::OnReceiveProcessList( const RequestProcessListCallback& callback, - mojo::Array<arc::mojom::RunningAppProcessInfoPtr> instance_processes) { + mojo::Array<mojom::RunningAppProcessInfoPtr> instance_processes) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); base::PostTaskAndReplyWithResult(
diff --git a/chrome/browser/chromeos/arc/arc_process_service.h b/chrome/browser/chromeos/arc/arc_process_service.h index 3ee704bf..3478a6a 100644 --- a/chrome/browser/chromeos/arc/arc_process_service.h +++ b/chrome/browser/chromeos/arc/arc_process_service.h
@@ -16,12 +16,15 @@ #include "base/single_thread_task_runner.h" #include "base/threading/thread.h" #include "chrome/browser/chromeos/arc/arc_process.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/common/process.mojom.h" #include "components/arc/instance_holder.h" +#include "mojo/public/cpp/bindings/array.h" namespace arc { +class ArcBridgeService; + // A single global entry to get a list of ARC processes. // // Call RequestAppProcessList() / RequestSystemProcessList() on the main UI @@ -97,8 +100,7 @@ private: void OnReceiveProcessList( const RequestProcessListCallback& callback, - const mojo::Array<arc::mojom::RunningAppProcessInfoPtr> - instance_processes); + const mojo::Array<mojom::RunningAppProcessInfoPtr> instance_processes); scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner();
diff --git a/chrome/browser/chromeos/arc/arc_settings_service.cc b/chrome/browser/chromeos/arc/arc_settings_service.cc index e22e010..4b269c5b 100644 --- a/chrome/browser/chromeos/arc/arc_settings_service.cc +++ b/chrome/browser/chromeos/arc/arc_settings_service.cc
@@ -23,6 +23,7 @@ #include "chromeos/network/network_state_handler_observer.h" #include "chromeos/settings/cros_settings_names.h" #include "chromeos/settings/timezone_settings.h" +#include "components/arc/arc_bridge_service.h" #include "components/arc/intent_helper/font_size_util.h" #include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/chromeos/arc/arc_settings_service.h b/chrome/browser/chromeos/arc/arc_settings_service.h index 7096f3da..85630d5 100644 --- a/chrome/browser/chromeos/arc/arc_settings_service.h +++ b/chrome/browser/chromeos/arc/arc_settings_service.h
@@ -8,12 +8,13 @@ #include <memory> #include "base/macros.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/common/intent_helper.mojom.h" #include "components/arc/instance_holder.h" namespace arc { +class ArcBridgeService; class ArcSettingsServiceImpl; class ArcSettingsService
diff --git a/chrome/browser/chromeos/arc/gpu_arc_video_service_host.cc b/chrome/browser/chromeos/arc/gpu_arc_video_service_host.cc index 4b9f13a..ec24339 100644 --- a/chrome/browser/chromeos/arc/gpu_arc_video_service_host.cc +++ b/chrome/browser/chromeos/arc/gpu_arc_video_service_host.cc
@@ -11,6 +11,7 @@ #include "base/logging.h" #include "base/message_loop/message_loop.h" #include "base/threading/thread_task_runner_handle.h" +#include "components/arc/arc_bridge_service.h" #include "components/arc/common/video_accelerator.mojom.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/gpu_service_registry.h" @@ -56,8 +57,7 @@ DISALLOW_COPY_AND_ASSIGN(VideoAcceleratorFactoryService); }; -GpuArcVideoServiceHost::GpuArcVideoServiceHost( - arc::ArcBridgeService* bridge_service) +GpuArcVideoServiceHost::GpuArcVideoServiceHost(ArcBridgeService* bridge_service) : ArcService(bridge_service), binding_(this) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); arc_bridge_service()->video()->AddObserver(this);
diff --git a/chrome/browser/chromeos/arc/gpu_arc_video_service_host.h b/chrome/browser/chromeos/arc/gpu_arc_video_service_host.h index b6f9540..95c5a43 100644 --- a/chrome/browser/chromeos/arc/gpu_arc_video_service_host.h +++ b/chrome/browser/chromeos/arc/gpu_arc_video_service_host.h
@@ -6,7 +6,6 @@ #define CHROME_BROWSER_CHROMEOS_ARC_GPU_ARC_VIDEO_SERVICE_HOST_H_ #include "base/macros.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" #include "components/arc/common/video.mojom.h" #include "components/arc/instance_holder.h" @@ -14,6 +13,8 @@ namespace arc { +class ArcBridgeService; + // This class takes requests for creating channels of video accelerators from // arc::VideoInstance and forwards these requests to GpuArcVideoServce. It also // returns the created channels back to the arc::VideoInstance. @@ -23,11 +24,11 @@ // // Lives on the UI thread. class GpuArcVideoServiceHost - : public arc::ArcService, - public arc::InstanceHolder<mojom::VideoInstance>::Observer, - public arc::mojom::VideoHost { + : public ArcService, + public InstanceHolder<mojom::VideoInstance>::Observer, + public mojom::VideoHost { public: - explicit GpuArcVideoServiceHost(arc::ArcBridgeService* bridge_service); + explicit GpuArcVideoServiceHost(ArcBridgeService* bridge_service); ~GpuArcVideoServiceHost() override; // arc::InstanceHolder<mojom::VideoInstance>::Observer implementation. @@ -41,7 +42,7 @@ const OnBootstrapVideoAcceleratorFactoryCallback& callback) override; private: - mojo::Binding<arc::mojom::VideoHost> binding_; + mojo::Binding<mojom::VideoHost> binding_; DISALLOW_COPY_AND_ASSIGN(GpuArcVideoServiceHost); };
diff --git a/chrome/browser/chromeos/camera_presence_notifier.cc b/chrome/browser/chromeos/camera_presence_notifier.cc index 2d44dd9..51ac268 100644 --- a/chrome/browser/chromeos/camera_presence_notifier.cc +++ b/chrome/browser/chromeos/camera_presence_notifier.cc
@@ -64,9 +64,8 @@ CameraDetector::camera_presence() == CameraDetector::kCameraPresent; if (is_camera_present != camera_present_on_last_check_) { camera_present_on_last_check_ = is_camera_present; - FOR_EACH_OBSERVER(Observer, - observers_, - OnCameraPresenceCheckDone(camera_present_on_last_check_)); + for (auto& observer : observers_) + observer.OnCameraPresenceCheckDone(camera_present_on_last_check_); } }
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index 86bbde1..d2acdd2 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -52,6 +52,8 @@ #include "chrome/browser/chromeos/login/helper.h" #include "chrome/browser/chromeos/login/lock/screen_locker.h" #include "chrome/browser/chromeos/login/login_wizard.h" +#include "chrome/browser/chromeos/login/quick_unlock/pin_storage.h" +#include "chrome/browser/chromeos/login/quick_unlock/pin_storage_factory.h" #include "chrome/browser/chromeos/login/session/user_session_manager.h" #include "chrome/browser/chromeos/login/startup_utils.h" #include "chrome/browser/chromeos/login/users/chrome_user_manager.h" @@ -689,6 +691,11 @@ // Start watching for low disk space events to notify the user. low_disk_notification_.reset(new LowDiskNotification()); + // Authenticate the user for PIN quick unlock. + PinStorage* pin_storage = PinStorageFactory::GetForProfile(profile()); + if (pin_storage) + pin_storage->MarkStrongAuth(); + ChromeBrowserMainPartsLinux::PostProfileInit(); }
diff --git a/chrome/browser/chromeos/device/input_service_proxy.cc b/chrome/browser/chromeos/device/input_service_proxy.cc index 3499cd5..601bc61 100644 --- a/chrome/browser/chromeos/device/input_service_proxy.cc +++ b/chrome/browser/chromeos/device/input_service_proxy.cc
@@ -146,12 +146,14 @@ void InputServiceProxy::OnDeviceAdded( const InputServiceLinux::InputDeviceInfo& info) { DCHECK(thread_checker_.CalledOnValidThread()); - FOR_EACH_OBSERVER(Observer, observers_, OnInputDeviceAdded(info)); + for (auto& observer : observers_) + observer.OnInputDeviceAdded(info); } void InputServiceProxy::OnDeviceRemoved(const std::string& id) { DCHECK(thread_checker_.CalledOnValidThread()); - FOR_EACH_OBSERVER(Observer, observers_, OnInputDeviceRemoved(id)); + for (auto& observer : observers_) + observer.OnInputDeviceRemoved(id); } } // namespace chromeos
diff --git a/chrome/browser/chromeos/drive/drive_integration_service.cc b/chrome/browser/chromeos/drive/drive_integration_service.cc index be83492..73e2e85e 100644 --- a/chrome/browser/chromeos/drive/drive_integration_service.cc +++ b/chrome/browser/chromeos/drive/drive_integration_service.cc
@@ -465,8 +465,8 @@ if (success) { logger_->Log(logging::LOG_INFO, "Drive mount point is added"); - FOR_EACH_OBSERVER(DriveIntegrationServiceObserver, observers_, - OnFileSystemMounted()); + for (auto& observer : observers_) + observer.OnFileSystemMounted(); } } @@ -476,8 +476,8 @@ if (!mount_point_name_.empty()) { job_list()->CancelAllJobs(); - FOR_EACH_OBSERVER(DriveIntegrationServiceObserver, observers_, - OnFileSystemBeingUnmounted()); + for (auto& observer : observers_) + observer.OnFileSystemBeingUnmounted(); storage::ExternalMountPoints* const mount_points = storage::ExternalMountPoints::GetSystemInstance();
diff --git a/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider_unittest.cc b/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider_unittest.cc index 19199db5..9e976aed 100644 --- a/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider_unittest.cc +++ b/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider_unittest.cc
@@ -5,8 +5,10 @@ #include "chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.h" #include <string> +#include <utility> #include "base/files/file_path.h" +#include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" #include "base/strings/string16.h" #include "base/values.h" @@ -434,12 +436,12 @@ // Verify that a platform app with socket dictionary permission can be // installed. { - base::DictionaryValue* const socket = new base::DictionaryValue(); + auto socket = base::MakeUnique<base::DictionaryValue>(); base::ListValue* const tcp_list = new base::ListValue(); tcp_list->AppendString("tcp-connect"); socket->Set("socket", tcp_list); base::ListValue* const permissions = new base::ListValue(); - permissions->Append(socket); + permissions->Append(std::move(socket)); base::DictionaryValue values; values.Set(extensions::manifest_keys::kPermissions, permissions); @@ -457,12 +459,12 @@ // Verify that a platform app with unknown dictionary permission cannot be // installed. { - base::DictionaryValue* const socket = new base::DictionaryValue(); + auto socket = base::MakeUnique<base::DictionaryValue>(); base::ListValue* const tcp_list = new base::ListValue(); tcp_list->AppendString("unknown_value"); socket->Set("unknown_key", tcp_list); base::ListValue* const permissions = new base::ListValue(); - permissions->Append(socket); + permissions->Append(std::move(socket)); base::DictionaryValue values; values.Set(extensions::manifest_keys::kPermissions, permissions);
diff --git a/chrome/browser/chromeos/extensions/wallpaper_api.cc b/chrome/browser/chromeos/extensions/wallpaper_api.cc index 080f49d..b780682 100644 --- a/chrome/browser/chromeos/extensions/wallpaper_api.cc +++ b/chrome/browser/chromeos/extensions/wallpaper_api.cc
@@ -248,8 +248,8 @@ extensions::EventRouter* event_router = extensions::EventRouter::Get(profile); std::unique_ptr<base::ListValue> event_args(new base::ListValue()); - event_args->Append(original_result->DeepCopy()); - event_args->Append(thumbnail_result->DeepCopy()); + event_args->Append(original_result->CreateDeepCopy()); + event_args->Append(thumbnail_result->CreateDeepCopy()); event_args->AppendString( extensions::api::wallpaper::ToString(params_->details.layout)); // Setting wallpaper from right click menu in 'Files' app is a feature that
diff --git a/chrome/browser/chromeos/file_manager/fake_disk_mount_manager.cc b/chrome/browser/chromeos/file_manager/fake_disk_mount_manager.cc index d9fe1e3..77f5bd9 100644 --- a/chrome/browser/chromeos/file_manager/fake_disk_mount_manager.cc +++ b/chrome/browser/chromeos/file_manager/fake_disk_mount_manager.cc
@@ -81,10 +81,10 @@ type, chromeos::disks::MOUNT_CONDITION_NONE); mount_points_.insert(make_pair(source_path, mount_point)); - FOR_EACH_OBSERVER(DiskMountManager::Observer, observers_, - OnMountEvent(DiskMountManager::MOUNTING, - chromeos::MOUNT_ERROR_NONE, - mount_point)); + for (auto& observer : observers_) { + observer.OnMountEvent(DiskMountManager::MOUNTING, + chromeos::MOUNT_ERROR_NONE, mount_point); + } } void FakeDiskMountManager::UnmountPath(const std::string& mount_path, @@ -98,10 +98,10 @@ const MountPointInfo mount_point = iter->second; mount_points_.erase(iter); - FOR_EACH_OBSERVER(DiskMountManager::Observer, observers_, - OnMountEvent(DiskMountManager::UNMOUNTING, - chromeos::MOUNT_ERROR_NONE, - mount_point)); + for (auto& observer : observers_) { + observer.OnMountEvent(DiskMountManager::UNMOUNTING, + chromeos::MOUNT_ERROR_NONE, mount_point); + } // Enqueue callback so that |FakeDiskMountManager::FinishAllUnmountRequest()| // can call them. @@ -140,9 +140,8 @@ void FakeDiskMountManager::InvokeDiskEventForTest( chromeos::disks::DiskMountManager::DiskEvent event, const chromeos::disks::DiskMountManager::Disk* disk) { - FOR_EACH_OBSERVER(chromeos::disks::DiskMountManager::Observer, - observers_, - OnDiskEvent(event, disk)); + for (auto& observer : observers_) + observer.OnDiskEvent(event, disk); } } // namespace file_manager
diff --git a/chrome/browser/chromeos/file_manager/file_browser_handlers.cc b/chrome/browser/chromeos/file_manager/file_browser_handlers.cc index 4d4985c..7ed9f34 100644 --- a/chrome/browser/chromeos/file_manager/file_browser_handlers.cc +++ b/chrome/browser/chromeos/file_manager/file_browser_handlers.cc
@@ -14,6 +14,7 @@ #include "base/files/file_util.h" #include "base/i18n/case_conversion.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/chromeos/drive/file_system_util.h" #include "chrome/browser/chromeos/file_manager/app_id.h" @@ -388,24 +389,24 @@ std::unique_ptr<base::ListValue> event_args(new base::ListValue()); event_args->AppendString(action_id_); - base::DictionaryValue* details = new base::DictionaryValue(); - event_args->Append(details); + auto details = base::MakeUnique<base::DictionaryValue>(); // Get file definitions. These will be replaced with Entry instances by // dispatchEvent() method from event_binding.js. base::ListValue* file_entries = new base::ListValue(); details->Set("entries", file_entries); + event_args->Append(std::move(details)); for (EntryDefinitionList::const_iterator iter = entry_definition_list->begin(); iter != entry_definition_list->end(); ++iter) { - base::DictionaryValue* file_def = new base::DictionaryValue(); - file_entries->Append(file_def); + auto file_def = base::MakeUnique<base::DictionaryValue>(); file_def->SetString("fileSystemName", iter->file_system_name); file_def->SetString("fileSystemRoot", iter->file_system_root_url); file_def->SetString("fileFullPath", "/" + iter->full_path.AsUTF8Unsafe()); file_def->SetBoolean("fileIsDirectory", iter->is_directory); + file_entries->Append(std::move(file_def)); } std::unique_ptr<extensions::Event> event(new extensions::Event(
diff --git a/chrome/browser/chromeos/file_manager/volume_manager.cc b/chrome/browser/chromeos/file_manager/volume_manager.cc index 86b788f..e227422 100644 --- a/chrome/browser/chromeos/file_manager/volume_manager.cc +++ b/chrome/browser/chromeos/file_manager/volume_manager.cc
@@ -44,7 +44,7 @@ const uint32_t kAccessCapabilityReadWrite = 0; const uint32_t kFilesystemTypeGenericHierarchical = 2; const char kFileManagerMTPMountNamePrefix[] = "fileman-mtp-"; -const char kMtpVolumeIdPrefix [] = "mtp:"; +const char kMtpVolumeIdPrefix[] = "mtp:"; const char kRootPath[] = "/"; // Registers |path| as the "Downloads" folder to the FileSystem API backend. @@ -508,8 +508,8 @@ } // Notify to observers. - FOR_EACH_OBSERVER(VolumeManagerObserver, observers_, - OnDiskAdded(*disk, mounting)); + for (auto& observer : observers_) + observer.OnDiskAdded(*disk, mounting); return; } @@ -523,8 +523,8 @@ } // Notify to observers. - FOR_EACH_OBSERVER(VolumeManagerObserver, observers_, - OnDiskRemoved(*disk)); + for (auto& observer : observers_) + observer.OnDiskRemoved(*disk); return; } NOTREACHED(); @@ -538,12 +538,12 @@ DVLOG(1) << "OnDeviceEvent: " << event << ", " << device_path; switch (event) { case chromeos::disks::DiskMountManager::DEVICE_ADDED: - FOR_EACH_OBSERVER(VolumeManagerObserver, observers_, - OnDeviceAdded(device_path)); + for (auto& observer : observers_) + observer.OnDeviceAdded(device_path); return; case chromeos::disks::DiskMountManager::DEVICE_REMOVED: { - FOR_EACH_OBSERVER( - VolumeManagerObserver, observers_, OnDeviceRemoved(device_path)); + for (auto& observer : observers_) + observer.OnDeviceRemoved(device_path); return; } case chromeos::disks::DiskMountManager::DEVICE_SCANNED: @@ -605,10 +605,10 @@ switch (event) { case chromeos::disks::DiskMountManager::FORMAT_STARTED: - FOR_EACH_OBSERVER( - VolumeManagerObserver, observers_, - OnFormatStarted(device_path, - error_code == chromeos::FORMAT_ERROR_NONE)); + for (auto& observer : observers_) { + observer.OnFormatStarted(device_path, + error_code == chromeos::FORMAT_ERROR_NONE); + } return; case chromeos::disks::DiskMountManager::FORMAT_COMPLETED: if (error_code == chromeos::FORMAT_ERROR_NONE) { @@ -622,10 +622,10 @@ GetExternalStorageAccessMode(profile_)); } - FOR_EACH_OBSERVER( - VolumeManagerObserver, observers_, - OnFormatCompleted(device_path, - error_code == chromeos::FORMAT_ERROR_NONE)); + for (auto& observer : observers_) { + observer.OnFormatCompleted(device_path, + error_code == chromeos::FORMAT_ERROR_NONE); + } return; } @@ -893,8 +893,8 @@ NUM_VOLUME_TYPE); } - FOR_EACH_OBSERVER(VolumeManagerObserver, observers_, - OnVolumeMounted(error_code, *volume)); + for (auto& observer : observers_) + observer.OnVolumeMounted(error_code, *volume); } void VolumeManager::DoUnmountEvent(chromeos::MountError error_code, @@ -904,8 +904,8 @@ if (error_code == chromeos::MOUNT_ERROR_NONE) mounted_volumes_.erase(volume->volume_id()); - FOR_EACH_OBSERVER(VolumeManagerObserver, observers_, - OnVolumeUnmounted(error_code, *volume.get())); + for (auto& observer : observers_) + observer.OnVolumeUnmounted(error_code, *volume.get()); } } // namespace file_manager
diff --git a/chrome/browser/chromeos/file_system_provider/provided_file_system.cc b/chrome/browser/chromeos/file_system_provider/provided_file_system.cc index db45db7..1788d39f 100644 --- a/chrome/browser/chromeos/file_system_provider/provided_file_system.cc +++ b/chrome/browser/chromeos/file_system_provider/provided_file_system.cc
@@ -687,13 +687,11 @@ } // Notify all observers. - FOR_EACH_OBSERVER(ProvidedFileSystemObserver, - observers_, - OnWatcherChanged(file_system_info_, - watcher_it->second, - change_type, - changes_ref, - auto_updater->CreateCallback())); + for (auto& observer : observers_) { + observer.OnWatcherChanged(file_system_info_, watcher_it->second, + change_type, changes_ref, + auto_updater->CreateCallback()); + } return AbortCallback(); } @@ -728,9 +726,8 @@ watcher->recursive = recursive; watcher->subscribers[subscriber.origin] = subscriber; - FOR_EACH_OBSERVER(ProvidedFileSystemObserver, - observers_, - OnWatcherListChanged(file_system_info_, watchers_)); + for (auto& observer : observers_) + observer.OnWatcherListChanged(file_system_info_, watchers_); callback.Run(base::File::FILE_OK); watcher_queue_.Complete(token); @@ -757,8 +754,8 @@ it->second.subscribers.erase(origin); - FOR_EACH_OBSERVER(ProvidedFileSystemObserver, observers_, - OnWatcherListChanged(file_system_info_, watchers_)); + for (auto& observer : observers_) + observer.OnWatcherListChanged(file_system_info_, watchers_); // If there are no more subscribers, then remove the watcher. if (it->second.subscribers.empty()) @@ -788,9 +785,8 @@ it->second.last_tag = args->tag; - FOR_EACH_OBSERVER(ProvidedFileSystemObserver, - observers_, - OnWatcherTagUpdated(file_system_info_, it->second)); + for (auto& observer : observers_) + observer.OnWatcherTagUpdated(file_system_info_, it->second); // If the watched entry is deleted, then remove the watcher. if (args->change_type == storage::WatcherManager::DELETED) {
diff --git a/chrome/browser/chromeos/file_system_provider/request_manager.cc b/chrome/browser/chromeos/file_system_provider/request_manager.cc index 2b6a76a..9dde1fa 100644 --- a/chrome/browser/chromeos/file_system_provider/request_manager.cc +++ b/chrome/browser/chromeos/file_system_provider/request_manager.cc
@@ -73,7 +73,8 @@ requests_[request_id] = request; ResetTimer(request_id); - FOR_EACH_OBSERVER(Observer, observers_, OnRequestCreated(request_id, type)); + for (auto& observer : observers_) + observer.OnRequestCreated(request_id, type); // Execute the request implementation. In case of an execution failure, // unregister and return 0. This may often happen, eg. if the providing @@ -84,7 +85,8 @@ return 0; } - FOR_EACH_OBSERVER(Observer, observers_, OnRequestExecuted(request_id)); + for (auto& observer : observers_) + observer.OnRequestExecuted(request_id); return request_id; } @@ -98,9 +100,8 @@ if (request_it == requests_.end()) return base::File::FILE_ERROR_NOT_FOUND; - FOR_EACH_OBSERVER(Observer, - observers_, - OnRequestFulfilled(request_id, *response.get(), has_more)); + for (auto& observer : observers_) + observer.OnRequestFulfilled(request_id, *response.get(), has_more); request_it->second->handler->OnSuccess(request_id, std::move(response), has_more); @@ -125,9 +126,8 @@ if (request_it == requests_.end()) return base::File::FILE_ERROR_NOT_FOUND; - FOR_EACH_OBSERVER(Observer, - observers_, - OnRequestRejected(request_id, *response.get(), error)); + for (auto& observer : observers_) + observer.OnRequestRejected(request_id, *response.get(), error); request_it->second->handler->OnError(request_id, std::move(response), error); DestroyRequest(request_id); @@ -165,7 +165,8 @@ RequestManager::Request::~Request() {} void RequestManager::OnRequestTimeout(int request_id) { - FOR_EACH_OBSERVER(Observer, observers_, OnRequestTimeouted(request_id)); + for (auto& observer : observers_) + observer.OnRequestTimeouted(request_id); if (!notification_manager_) { RejectRequest(request_id, std::unique_ptr<RequestValue>(new RequestValue()), @@ -257,7 +258,8 @@ if (notification_manager_) notification_manager_->HideUnresponsiveNotification(request_id); - FOR_EACH_OBSERVER(Observer, observers_, OnRequestDestroyed(request_id)); + for (auto& observer : observers_) + observer.OnRequestDestroyed(request_id); TRACE_EVENT_ASYNC_END0( "file_system_provider", "RequestManager::Request", request_id);
diff --git a/chrome/browser/chromeos/file_system_provider/service.cc b/chrome/browser/chromeos/file_system_provider/service.cc index 4b50698..157cfca 100644 --- a/chrome/browser/chromeos/file_system_provider/service.cc +++ b/chrome/browser/chromeos/file_system_provider/service.cc
@@ -128,19 +128,20 @@ // If already exists a file system provided by the same extension with this // id, then abort. if (GetProvidedFileSystem(extension_id, options.file_system_id)) { - FOR_EACH_OBSERVER( - Observer, observers_, - OnProvidedFileSystemMount(ProvidedFileSystemInfo(), context, - base::File::FILE_ERROR_EXISTS)); + for (auto& observer : observers_) { + observer.OnProvidedFileSystemMount(ProvidedFileSystemInfo(), context, + base::File::FILE_ERROR_EXISTS); + } return base::File::FILE_ERROR_EXISTS; } // Restrict number of file systems to prevent system abusing. if (file_system_map_.size() + 1 > kMaxFileSystems) { - FOR_EACH_OBSERVER( - Observer, observers_, - OnProvidedFileSystemMount(ProvidedFileSystemInfo(), context, - base::File::FILE_ERROR_TOO_MANY_OPENED)); + for (auto& observer : observers_) { + observer.OnProvidedFileSystemMount( + ProvidedFileSystemInfo(), context, + base::File::FILE_ERROR_TOO_MANY_OPENED); + } return base::File::FILE_ERROR_TOO_MANY_OPENED; } @@ -159,10 +160,11 @@ storage::FileSystemMountOption( storage::FlushPolicy::FLUSH_ON_COMPLETION), mount_path)) { - FOR_EACH_OBSERVER( - Observer, observers_, - OnProvidedFileSystemMount(ProvidedFileSystemInfo(), context, - base::File::FILE_ERROR_INVALID_OPERATION)); + for (auto& observer : observers_) { + observer.OnProvidedFileSystemMount( + ProvidedFileSystemInfo(), context, + base::File::FILE_ERROR_INVALID_OPERATION); + } return base::File::FILE_ERROR_INVALID_OPERATION; } @@ -195,9 +197,10 @@ FileSystemKey(extension_id, options.file_system_id); registry_->RememberFileSystem(file_system_info, *file_system->GetWatchers()); - FOR_EACH_OBSERVER(Observer, observers_, - OnProvidedFileSystemMount(file_system_info, context, - base::File::FILE_OK)); + for (auto& observer : observers_) { + observer.OnProvidedFileSystemMount(file_system_info, context, + base::File::FILE_OK); + } return base::File::FILE_OK; } @@ -211,11 +214,10 @@ file_system_map_.find(FileSystemKey(extension_id, file_system_id)); if (file_system_it == file_system_map_.end()) { const ProvidedFileSystemInfo empty_file_system_info; - FOR_EACH_OBSERVER( - Observer, - observers_, - OnProvidedFileSystemUnmount(empty_file_system_info, - base::File::FILE_ERROR_NOT_FOUND)); + for (auto& observer : observers_) { + observer.OnProvidedFileSystemUnmount(empty_file_system_info, + base::File::FILE_ERROR_NOT_FOUND); + } return base::File::FILE_ERROR_NOT_FOUND; } @@ -229,18 +231,15 @@ const std::string mount_point_name = file_system_info.mount_path().BaseName().value(); if (!mount_points->RevokeFileSystem(mount_point_name)) { - FOR_EACH_OBSERVER( - Observer, - observers_, - OnProvidedFileSystemUnmount(file_system_info, - base::File::FILE_ERROR_INVALID_OPERATION)); + for (auto& observer : observers_) { + observer.OnProvidedFileSystemUnmount( + file_system_info, base::File::FILE_ERROR_INVALID_OPERATION); + } return base::File::FILE_ERROR_INVALID_OPERATION; } - FOR_EACH_OBSERVER( - Observer, - observers_, - OnProvidedFileSystemUnmount(file_system_info, base::File::FILE_OK)); + for (auto& observer : observers_) + observer.OnProvidedFileSystemUnmount(file_system_info, base::File::FILE_OK); mount_point_name_to_key_map_.erase(mount_point_name); @@ -437,9 +436,8 @@ // called by the provided file system. In case of success mount() will be // invoked, and observers notified, so there is no need to call them now. if (error != base::File::FILE_OK) { - FOR_EACH_OBSERVER(Observer, - observers_, - OnProvidedFileSystemUnmount(file_system_info, error)); + for (auto& observer : observers_) + observer.OnProvidedFileSystemUnmount(file_system_info, error); } }
diff --git a/chrome/browser/chromeos/first_run/drive_first_run_controller.cc b/chrome/browser/chromeos/first_run/drive_first_run_controller.cc index f5908cec..a384608 100644 --- a/chrome/browser/chromeos/first_run/drive_first_run_controller.cc +++ b/chrome/browser/chromeos/first_run/drive_first_run_controller.cc
@@ -425,7 +425,8 @@ void DriveFirstRunController::OnWebContentsTimedOut() { LOG(WARNING) << "Timed out waiting for web contents."; - FOR_EACH_OBSERVER(Observer, observer_list_, OnTimedOut()); + for (auto& observer : observer_list_) + observer.OnTimedOut(); OnOfflineInit(false, OUTCOME_WEB_CONTENTS_TIMED_OUT); } @@ -442,7 +443,8 @@ ShowNotification(); UMA_HISTOGRAM_ENUMERATION("DriveOffline.CrosAutoEnableOutcome", outcome, OUTCOME_MAX); - FOR_EACH_OBSERVER(Observer, observer_list_, OnCompletion(success)); + for (auto& observer : observer_list_) + observer.OnCompletion(success); CleanUp(); }
diff --git a/chrome/browser/chromeos/input_method/candidate_window_controller_impl.cc b/chrome/browser/chromeos/input_method/candidate_window_controller_impl.cc index 2aaa8086..5a8248e 100644 --- a/chrome/browser/chromeos/input_method/candidate_window_controller_impl.cc +++ b/chrome/browser/chromeos/input_method/candidate_window_controller_impl.cc
@@ -55,8 +55,8 @@ views::Widget* widget = candidate_window_view_->InitWidget(); widget->AddObserver(this); widget->Show(); - FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_, - CandidateWindowOpened()); + for (auto& observer : observers_) + observer.CandidateWindowOpened(); } void CandidateWindowControllerImpl::Hide() { @@ -168,8 +168,8 @@ } void CandidateWindowControllerImpl::OnCandidateCommitted(int index) { - FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_, - CandidateClicked(index)); + for (auto& observer : observers_) + observer.CandidateClicked(index); } void CandidateWindowControllerImpl::OnWidgetClosing(views::Widget* widget) { @@ -181,8 +181,8 @@ widget->RemoveObserver(this); candidate_window_view_->RemoveObserver(this); candidate_window_view_ = NULL; - FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_, - CandidateWindowClosed()); + for (auto& observer : observers_) + observer.CandidateWindowClosed(); } }
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc index bd20ea8..fb5e5f4 100644 --- a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc +++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
@@ -1043,8 +1043,8 @@ } // Update input method indicators (e.g. "US", "DV") in Chrome windows. - FOR_EACH_OBSERVER(InputMethodManager::Observer, observers_, - InputMethodChanged(this, profile, show_message)); + for (auto& observer : observers_) + observer.InputMethodChanged(this, profile, show_message); // Update the current input method in IME menu. NotifyImeMenuListChanged(); } @@ -1166,15 +1166,13 @@ } void InputMethodManagerImpl::CandidateWindowOpened() { - FOR_EACH_OBSERVER(InputMethodManager::CandidateWindowObserver, - candidate_window_observers_, - CandidateWindowOpened(this)); + for (auto& observer : candidate_window_observers_) + observer.CandidateWindowOpened(this); } void InputMethodManagerImpl::CandidateWindowClosed() { - FOR_EACH_OBSERVER(InputMethodManager::CandidateWindowObserver, - candidate_window_observers_, - CandidateWindowClosed(this)); + for (auto& observer : candidate_window_observers_) + observer.CandidateWindowClosed(this); } void InputMethodManagerImpl::ImeMenuActivationChanged(bool is_active) { @@ -1185,8 +1183,8 @@ } void InputMethodManagerImpl::NotifyImeMenuListChanged() { - FOR_EACH_OBSERVER(InputMethodManager::ImeMenuObserver, ime_menu_observers_, - ImeMenuListChanged()); + for (auto& observer : ime_menu_observers_) + observer.ImeMenuListChanged(); } void InputMethodManagerImpl::MaybeInitializeCandidateWindowController() { @@ -1201,8 +1199,8 @@ void InputMethodManagerImpl::NotifyImeMenuItemsChanged( const std::string& engine_id, const std::vector<InputMethodManager::MenuItem>& items) { - FOR_EACH_OBSERVER(InputMethodManager::ImeMenuObserver, ime_menu_observers_, - ImeMenuItemsChanged(engine_id, items)); + for (auto& observer : ime_menu_observers_) + observer.ImeMenuItemsChanged(engine_id, items); } void InputMethodManagerImpl::MaybeNotifyImeMenuActivationChanged() { @@ -1210,8 +1208,8 @@ return; is_ime_menu_activated_ = state_->menu_activated; - FOR_EACH_OBSERVER(InputMethodManager::ImeMenuObserver, ime_menu_observers_, - ImeMenuActivationChanged(is_ime_menu_activated_)); + for (auto& observer : ime_menu_observers_) + observer.ImeMenuActivationChanged(is_ime_menu_activated_); UMA_HISTOGRAM_BOOLEAN("InputMethod.ImeMenu.ActivationChanged", is_ime_menu_activated_); }
diff --git a/chrome/browser/chromeos/input_method/mock_candidate_window_controller.cc b/chrome/browser/chromeos/input_method/mock_candidate_window_controller.cc index de791c9c6..5c95b59 100644 --- a/chrome/browser/chromeos/input_method/mock_candidate_window_controller.cc +++ b/chrome/browser/chromeos/input_method/mock_candidate_window_controller.cc
@@ -33,13 +33,13 @@ } void MockCandidateWindowController::NotifyCandidateWindowOpened() { - FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_, - CandidateWindowOpened()); + for (auto& observer : observers_) + observer.CandidateWindowOpened(); } void MockCandidateWindowController::NotifyCandidateWindowClosed() { - FOR_EACH_OBSERVER(CandidateWindowController::Observer, observers_, - CandidateWindowClosed()); + for (auto& observer : observers_) + observer.CandidateWindowClosed(); } } // namespace input_method
diff --git a/chrome/browser/chromeos/login/app_launch_signin_screen.cc b/chrome/browser/chromeos/login/app_launch_signin_screen.cc index 1356b0d..8a971e46 100644 --- a/chrome/browser/chromeos/login/app_launch_signin_screen.cc +++ b/chrome/browser/chromeos/login/app_launch_signin_screen.cc
@@ -4,6 +4,9 @@ #include "chrome/browser/chromeos/login/app_launch_signin_screen.h" +#include <utility> + +#include "base/memory/ptr_util.h" #include "base/values.h" #include "chrome/browser/chromeos/login/help_app_launcher.h" #include "chrome/browser/chromeos/login/screens/user_selection_screen.h" @@ -211,15 +214,13 @@ UserSelectionScreen::ShouldForceOnlineSignIn(*it) ? proximity_auth::ScreenlockBridge::LockHandler::ONLINE_SIGN_IN : proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD; - base::DictionaryValue* user_dict = new base::DictionaryValue(); + auto user_dict = base::MakeUnique<base::DictionaryValue>(); UserSelectionScreen::FillUserDictionary( - *it, - true, /* is_owner */ - false, /* is_signin_to_add */ - initial_auth_type, - NULL, /* public_session_recommended_locales */ - user_dict); - users_list.Append(user_dict); + *it, true, /* is_owner */ + false, /* is_signin_to_add */ + initial_auth_type, NULL, /* public_session_recommended_locales */ + user_dict.get()); + users_list.Append(std::move(user_dict)); } webui_handler_->LoadUsers(users_list, false);
diff --git a/chrome/browser/chromeos/login/screens/network_screen.cc b/chrome/browser/chromeos/login/screens/network_screen.cc index f04bcb8..0370d44d 100644 --- a/chrome/browser/chromeos/login/screens/network_screen.cc +++ b/chrome/browser/chromeos/login/screens/network_screen.cc
@@ -439,7 +439,8 @@ selected_language_code_); if (view_) view_->ReloadLocalizedContent(); - FOR_EACH_OBSERVER(Observer, observers_, OnLanguageListReloaded()); + for (auto& observer : observers_) + observer.OnLanguageListReloaded(); } void NetworkScreen::OnSystemTimezoneChanged() {
diff --git a/chrome/browser/chromeos/login/screens/user_selection_screen.cc b/chrome/browser/chromeos/login/screens/user_selection_screen.cc index c4d6a6f..1564705 100644 --- a/chrome/browser/chromeos/login/screens/user_selection_screen.cc +++ b/chrome/browser/chromeos/login/screens/user_selection_screen.cc
@@ -6,8 +6,11 @@ #include <stddef.h> +#include <utility> + #include "base/location.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/values.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" @@ -393,18 +396,14 @@ : OFFLINE_PASSWORD); user_auth_type_map_[account_id] = initial_auth_type; - base::DictionaryValue* user_dict = new base::DictionaryValue(); + auto user_dict = base::MakeUnique<base::DictionaryValue>(); const std::vector<std::string>* public_session_recommended_locales = public_session_recommended_locales_.find(account_id) == public_session_recommended_locales_.end() ? &kEmptyRecommendedLocales : &public_session_recommended_locales_[account_id]; - FillUserDictionary(*it, - is_owner, - is_signin_to_add, - initial_auth_type, - public_session_recommended_locales, - user_dict); + FillUserDictionary(*it, is_owner, is_signin_to_add, initial_auth_type, + public_session_recommended_locales, user_dict.get()); bool signed_in = (*it)->is_logged_in(); // Single user check here is necessary because owner info might not be @@ -414,7 +413,7 @@ ((!single_user || is_enterprise_managed) && account_id.is_valid() && !is_owner && !is_public_account && !signed_in && !is_signin_to_add); user_dict->SetBoolean(kKeyCanRemove, can_remove_user); - users_list.Append(user_dict); + users_list.Append(std::move(user_dict)); } handler_->LoadUsers(users_list, show_guest_);
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc index dddb1045..751d50e 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.cc +++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -46,8 +46,6 @@ #include "chrome/browser/chromeos/login/helper.h" #include "chrome/browser/chromeos/login/lock/screen_locker.h" #include "chrome/browser/chromeos/login/profile_auth_data.h" -#include "chrome/browser/chromeos/login/quick_unlock/pin_storage.h" -#include "chrome/browser/chromeos/login/quick_unlock/pin_storage_factory.h" #include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter.h" #include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter_factory.h" #include "chrome/browser/chromeos/login/signin/oauth2_login_manager.h" @@ -1282,12 +1280,6 @@ (oobe_controller && oobe_controller->skip_post_login_screens()) || cmdline->HasSwitch(chromeos::switches::kOobeSkipPostLogin); - // The user just signed into the profile session, so it means that they - // entered a password (or used easy unlock). We will enable quick unlock. - PinStorage* pin_storage = PinStorageFactory::GetForProfile(profile); - if (pin_storage) - pin_storage->MarkStrongAuth(); - if (user_manager->IsCurrentUserNew() && !skip_post_login_screens) { // Don't specify start URLs if the administrator has configured the start // URLs via policy. @@ -1529,9 +1521,8 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); user_sessions_restored_ = true; user_sessions_restore_in_progress_ = false; - FOR_EACH_OBSERVER(chromeos::UserSessionStateObserver, - session_state_observer_list_, - PendingUserSessionsRestoreFinished()); + for (auto& observer : session_state_observer_list_) + observer.PendingUserSessionsRestoreFinished(); } void UserSessionManager::UpdateEasyUnlockKeys(const UserContext& user_context) { @@ -1760,9 +1751,8 @@ // Check to see if this profile should show EndOfLife Notification and show // the message accordingly. - if (!ShouldShowEolNotification(profile)) - return; - CheckEolStatus(profile); + if (ShouldShowEolNotification(profile)) + CheckEolStatus(profile); } void UserSessionManager::RespectLocalePreferenceWrapper(
diff --git a/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc b/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc index 2879f7f0..69f2f86 100644 --- a/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc +++ b/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc
@@ -198,8 +198,8 @@ GetTokenService()->UpdateCredentials(account_id, refresh_token_); FireRefreshTokensLoaded(); - FOR_EACH_OBSERVER(Observer, observer_list_, - OnNewRefreshTokenAvaiable(user_profile_)); + for (auto& observer : observer_list_) + observer.OnNewRefreshTokenAvaiable(user_profile_); } void OAuth2LoginManager::FireRefreshTokensLoaded() { @@ -416,8 +416,8 @@ base::Time::Now() - session_restore_start_); } - FOR_EACH_OBSERVER(Observer, observer_list_, - OnSessionRestoreStateChanged(user_profile_, state_)); + for (auto& observer : observer_list_) + observer.OnSessionRestoreStateChanged(user_profile_, state_); } void OAuth2LoginManager::SetSessionRestoreStartForTesting(
diff --git a/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc b/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc index 25d4048..5acd784 100644 --- a/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc +++ b/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc
@@ -4,9 +4,12 @@ #include "chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.h" +#include <utility> + #include "ash/common/shelf/wm_shelf.h" #include "ash/common/wallpaper/wallpaper_controller.h" #include "ash/common/wm_shell.h" +#include "base/memory/ptr_util.h" #include "base/rand_util.h" #include "base/values.h" #include "chrome/browser/chromeos/camera_detector.h" @@ -538,8 +541,7 @@ static_cast<base::DictionaryValue*>(it.value().DeepCopy()); // Copy that would be passed to WebUI. It has some extra values for // displaying, but does not contain sensitive data, such as master password. - base::DictionaryValue* ui_copy = - static_cast<base::DictionaryValue*>(new base::DictionaryValue()); + auto ui_copy = base::MakeUnique<base::DictionaryValue>(); int avatar_index = SupervisedUserCreationController::kDummyAvatarIndex; std::string chromeos_avatar; @@ -590,7 +592,7 @@ ui_copy->SetString("id", it.key()); existing_users_->Set(it.key(), local_copy); - ui_users->Append(ui_copy); + ui_users->Append(std::move(ui_copy)); } actor_->ShowExistingSupervisedUsers(ui_users.get()); }
diff --git a/chrome/browser/chromeos/login/ui/user_adding_screen.cc b/chrome/browser/chromeos/login/ui/user_adding_screen.cc index 0e845847..293fba11 100644 --- a/chrome/browser/chromeos/login/ui/user_adding_screen.cc +++ b/chrome/browser/chromeos/login/ui/user_adding_screen.cc
@@ -57,7 +57,8 @@ g_browser_process->platform_part()->SessionManager()->SetSessionState( session_manager::SESSION_STATE_LOGIN_SECONDARY); - FOR_EACH_OBSERVER(Observer, observers_, OnUserAddingStarted()); + for (auto& observer : observers_) + observer.OnUserAddingStarted(); } void UserAddingScreenImpl::Cancel() { @@ -92,7 +93,8 @@ g_browser_process->platform_part()->SessionManager()->SetSessionState( session_manager::SESSION_STATE_ACTIVE); - FOR_EACH_OBSERVER(Observer, observers_, OnUserAddingFinished()); + for (auto& observer : observers_) + observer.OnUserAddingFinished(); } // static @@ -117,4 +119,3 @@ } } // namespace chromeos -
diff --git a/chrome/browser/chromeos/login/ui/webui_login_view.cc b/chrome/browser/chromeos/login/ui/webui_login_view.cc index e8355fe2..01224657 100644 --- a/chrome/browser/chromeos/login/ui/webui_login_view.cc +++ b/chrome/browser/chromeos/login/ui/webui_login_view.cc
@@ -233,9 +233,8 @@ } WebUILoginView::~WebUILoginView() { - FOR_EACH_OBSERVER(web_modal::ModalDialogHostObserver, - observer_list_, - OnHostDestroying()); + for (auto& observer : observer_list_) + observer.OnHostDestroying(); if (!chrome::IsRunningInMash() && ash::Shell::GetInstance()->HasPrimaryStatusArea()) { @@ -443,9 +442,8 @@ DCHECK(webui_login_); webui_login_->SetBoundsRect(bounds()); - FOR_EACH_OBSERVER(web_modal::ModalDialogHostObserver, - observer_list_, - OnPositionRequiresUpdate()); + for (auto& observer : observer_list_) + observer.OnPositionRequiresUpdate(); } void WebUILoginView::OnLocaleChanged() {
diff --git a/chrome/browser/chromeos/login/users/avatar/user_image_sync_observer.cc b/chrome/browser/chromeos/login/users/avatar/user_image_sync_observer.cc index d41ea4be..696aa7f 100644 --- a/chrome/browser/chromeos/login/users/avatar/user_image_sync_observer.cc +++ b/chrome/browser/chromeos/login/users/avatar/user_image_sync_observer.cc
@@ -105,8 +105,8 @@ UpdateLocalImageFromSynced(); local_image_updated = true; } - FOR_EACH_OBSERVER(UserImageSyncObserver::Observer, observer_list_, - OnInitialSync(local_image_updated)); + for (auto& observer : observer_list_) + observer.OnInitialSync(local_image_updated); } void UserImageSyncObserver::OnPreferenceChanged(const std::string& pref_name) { @@ -199,4 +199,3 @@ } } // namespace chromeos -
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc index 34437eb..5523f1b 100644 --- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc +++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc
@@ -336,7 +336,7 @@ // The only known case for this check to fail is global destruction during // wallpaper load. It should never happen. if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) - return; // We are in a process of global destruction. + return; // We are in a process of global destruction. timer.Stop(); // Erase reference to self. @@ -881,8 +881,10 @@ } } - if (loading_.empty()) - FOR_EACH_OBSERVER(Observer, observers_, OnPendingListEmptyForTesting()); + if (loading_.empty()) { + for (auto& observer : observers_) + observer.OnPendingListEmptyForTesting(); + } } void WallpaperManager::SetPolicyControlledWallpaper(
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc index b69c59a70..6042585 100644 --- a/chrome/browser/chromeos/login/wizard_controller.cc +++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -620,7 +620,8 @@ } void WizardController::OnSessionStart() { - FOR_EACH_OBSERVER(Observer, observer_list_, OnSessionStart()); + for (auto& observer : observer_list_) + observer.OnSessionStart(); } void WizardController::SkipUpdateEnrollAfterEula() { @@ -917,7 +918,8 @@ smooth_show_timer_.Stop(); - FOR_EACH_OBSERVER(Observer, observer_list_, OnScreenChanged(current_screen_)); + for (auto& observer : observer_list_) + observer.OnScreenChanged(current_screen_); current_screen_->Show(); }
diff --git a/chrome/browser/chromeos/mobile/mobile_activator.cc b/chrome/browser/chromeos/mobile/mobile_activator.cc index 32b179b7..58a8613 100644 --- a/chrome/browser/chromeos/mobile/mobile_activator.cc +++ b/chrome/browser/chromeos/mobile/mobile_activator.cc
@@ -998,8 +998,8 @@ state_ = new_state; // Signal to observers layer that the state is changing. - FOR_EACH_OBSERVER(Observer, observers_, - OnActivationStateChanged(network, state_, error_description)); + for (auto& observer : observers_) + observer.OnActivationStateChanged(network, state_, error_description); // Pick action that should happen on entering the new state. switch (new_state) {
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl.cc b/chrome/browser/chromeos/net/network_portal_detector_impl.cc index bb99b868..b4691cdd 100644 --- a/chrome/browser/chromeos/net/network_portal_detector_impl.cc +++ b/chrome/browser/chromeos/net/network_portal_detector_impl.cc
@@ -599,8 +599,8 @@ void NetworkPortalDetectorImpl::NotifyDetectionCompleted( const NetworkState* network, const CaptivePortalState& state) { - FOR_EACH_OBSERVER( - Observer, observers_, OnPortalDetectionCompleted(network, state)); + for (auto& observer : observers_) + observer.OnPortalDetectionCompleted(network, state); } bool NetworkPortalDetectorImpl::AttemptTimeoutIsCancelledForTesting() const {
diff --git a/chrome/browser/chromeos/net/network_portal_detector_test_impl.cc b/chrome/browser/chromeos/net/network_portal_detector_test_impl.cc index 2c4e8bd..cfaa5c55 100644 --- a/chrome/browser/chromeos/net/network_portal_detector_test_impl.cc +++ b/chrome/browser/chromeos/net/network_portal_detector_test_impl.cc
@@ -39,8 +39,8 @@ CaptivePortalState state; if (default_network_ && portal_state_map_.count(default_network_->guid())) state = portal_state_map_[default_network_->guid()]; - FOR_EACH_OBSERVER(Observer, observers_, - OnPortalDetectionCompleted(default_network_.get(), state)); + for (auto& observer : observers_) + observer.OnPortalDetectionCompleted(default_network_.get(), state); } void NetworkPortalDetectorTestImpl::AddObserver(Observer* observer) {
diff --git a/chrome/browser/chromeos/options/cert_library.cc b/chrome/browser/chromeos/options/cert_library.cc index 241debb..00084f6 100644 --- a/chrome/browser/chromeos/options/cert_library.cc +++ b/chrome/browser/chromeos/options/cert_library.cc
@@ -250,8 +250,8 @@ VLOG(1) << "server_certs_: " << server_certs_.size(); VLOG(1) << "server_ca_certs_: " << server_ca_certs_.size(); - FOR_EACH_OBSERVER(CertLibrary::Observer, observer_list_, - OnCertificatesLoaded(initial_load)); + for (auto& observer : observer_list_) + observer.OnCertificatesLoaded(initial_load); } net::X509Certificate* CertLibrary::GetCertificateAt(CertType type,
diff --git a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc index 0b356b4d..090ac96 100644 --- a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc +++ b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc
@@ -266,8 +266,8 @@ em::PolicyData policy_data; policy_data.set_username(user_id_); CHECK(settings.SerializeToString(policy_data.mutable_policy_value())); - FOR_EACH_OBSERVER(OwnerSettingsService::Observer, observers_, - OnTentativeChangesInPolicy(policy_data)); + for (auto& observer : observers_) + observer.OnTentativeChangesInPolicy(policy_data); StorePendingChanges(); return true; } @@ -281,7 +281,7 @@ std::unique_ptr<base::ListValue> new_value( old_value ? static_cast<const base::ListValue*>(old_value)->DeepCopy() : new base::ListValue()); - new_value->Append(value.DeepCopy()); + new_value->Append(value.CreateDeepCopy()); return Set(setting, *new_value); } @@ -730,8 +730,8 @@ void OwnerSettingsServiceChromeOS::ReportStatusAndContinueStoring( bool success) { store_settings_factory_.InvalidateWeakPtrs(); - FOR_EACH_OBSERVER(OwnerSettingsService::Observer, observers_, - OnSignedPolicyStored(success)); + for (auto& observer : observers_) + observer.OnSignedPolicyStored(success); StorePendingChanges(); }
diff --git a/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl.cc b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl.cc index 9fd75e9..d9ec782 100644 --- a/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl.cc +++ b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl.cc
@@ -254,7 +254,6 @@ // now, destroy the device-global one. DestroyDeviceInvalidationService(); } - } void @@ -336,9 +335,8 @@ invalidation::InvalidationService* invalidation_service) { DCHECK(!invalidation_service_); invalidation_service_ = invalidation_service; - FOR_EACH_OBSERVER(Consumer, - consumers_, - OnInvalidationServiceSet(invalidation_service_)); + for (auto& observer : consumers_) + observer.OnInvalidationServiceSet(invalidation_service_); } void
diff --git a/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos_unittest.cc b/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos_unittest.cc index 2f261cd..fd7559d 100644 --- a/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos_unittest.cc +++ b/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos_unittest.cc
@@ -321,7 +321,7 @@ auto entry1_dict = base::MakeUnique<base::DictionaryValue>(); entry1_dict->Set(ash::launcher::kPinnedAppsPrefAppIDPath, entry1.DeepCopy()); expected_pinned_apps.Append(std::move(entry1_dict)); - list.Append(entry1.DeepCopy()); + list.Append(entry1.CreateDeepCopy()); policy_map.Set(key::kPinnedLauncherApps, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, list.CreateDeepCopy(), nullptr);
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc index 7703789..243ca355 100644 --- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc +++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
@@ -316,13 +316,13 @@ } void DeviceCloudPolicyManagerChromeOS::NotifyConnected() { - FOR_EACH_OBSERVER( - Observer, observers_, OnDeviceCloudPolicyManagerConnected()); + for (auto& observer : observers_) + observer.OnDeviceCloudPolicyManagerConnected(); } void DeviceCloudPolicyManagerChromeOS::NotifyDisconnected() { - FOR_EACH_OBSERVER( - Observer, observers_, OnDeviceCloudPolicyManagerDisconnected()); + for (auto& observer : observers_) + observer.OnDeviceCloudPolicyManagerDisconnected(); } void DeviceCloudPolicyManagerChromeOS::CreateStatusUploader() {
diff --git a/chrome/browser/chromeos/policy/device_local_account_policy_service.cc b/chrome/browser/chromeos/policy/device_local_account_policy_service.cc index 65293fc..3cd643f 100644 --- a/chrome/browser/chromeos/policy/device_local_account_policy_service.cc +++ b/chrome/browser/chromeos/policy/device_local_account_policy_service.cc
@@ -532,7 +532,8 @@ component_policy_cache_root_, subdirectories_to_keep)); - FOR_EACH_OBSERVER(Observer, observers_, OnDeviceLocalAccountsChanged()); + for (auto& observer : observers_) + observer.OnDeviceLocalAccountsChanged(); } void DeviceLocalAccountPolicyService::DeleteBrokers(PolicyBrokerMap* map) { @@ -566,7 +567,8 @@ void DeviceLocalAccountPolicyService::NotifyPolicyUpdated( const std::string& user_id) { - FOR_EACH_OBSERVER(Observer, observers_, OnPolicyUpdated(user_id)); + for (auto& observer : observers_) + observer.OnPolicyUpdated(user_id); } } // namespace policy
diff --git a/chrome/browser/chromeos/policy/network_configuration_updater_unittest.cc b/chrome/browser/chromeos/policy/network_configuration_updater_unittest.cc index 8634ade..a7ffe0bf 100644 --- a/chrome/browser/chromeos/policy/network_configuration_updater_unittest.cc +++ b/chrome/browser/chromeos/policy/network_configuration_updater_unittest.cc
@@ -185,10 +185,8 @@ } void AppendAll(const base::ListValue& from, base::ListValue* to) { - for (base::ListValue::const_iterator it = from.begin(); it != from.end(); - ++it) { - to->Append((*it)->DeepCopy()); - } + for (const auto& value : from) + to->Append(value->CreateDeepCopy()); } // Matcher to match base::Value.
diff --git a/chrome/browser/chromeos/policy/user_network_configuration_updater.cc b/chrome/browser/chromeos/policy/user_network_configuration_updater.cc index 036ffba..7a29194 100644 --- a/chrome/browser/chromeos/policy/user_network_configuration_updater.cc +++ b/chrome/browser/chromeos/policy/user_network_configuration_updater.cc
@@ -156,9 +156,8 @@ } void UserNetworkConfigurationUpdater::NotifyTrustAnchorsChanged() { - FOR_EACH_OBSERVER(WebTrustedCertsObserver, - observer_list_, - OnTrustAnchorsChanged(web_trust_certs_)); + for (auto& observer : observer_list_) + observer.OnTrustAnchorsChanged(web_trust_certs_); } } // namespace policy
diff --git a/chrome/browser/chromeos/power/renderer_freezer.cc b/chrome/browser/chromeos/power/renderer_freezer.cc index e5459fd..93b4e665 100644 --- a/chrome/browser/chromeos/power/renderer_freezer.cc +++ b/chrome/browser/chromeos/power/renderer_freezer.cc
@@ -34,16 +34,12 @@ RendererFreezer::RendererFreezer( std::unique_ptr<RendererFreezer::Delegate> delegate) : delegate_(std::move(delegate)), weak_factory_(this) { - // TODO(derat): Remove after http://crbug.com/648580 is fixed. - VLOG(1) << "Creating RendererFreezer " << this; delegate_->CheckCanFreezeRenderers( base::Bind(&RendererFreezer::OnCheckCanFreezeRenderersComplete, weak_factory_.GetWeakPtr())); } RendererFreezer::~RendererFreezer() { - // TODO(derat): Remove after http://crbug.com/648580 is fixed. - VLOG(1) << "Destroying RendererFreezer " << this; for (int rph_id : gcm_extension_processes_) { content::RenderProcessHost* host = content::RenderProcessHost::FromID(rph_id); @@ -53,8 +49,6 @@ } void RendererFreezer::SuspendImminent() { - // TODO(derat): Remove after http://crbug.com/648580 is fixed. - VLOG(1) << "Asking delegate to freeze renderers"; // All the delegate's operations are asynchronous so they may not complete // before the system suspends. This is ok since the renderers only need to be // frozen in dark resume. As long as they do get frozen soon after we enter @@ -63,8 +57,6 @@ } void RendererFreezer::SuspendDone() { - // TODO(derat): Remove after http://crbug.com/648580 is fixed. - VLOG(1) << "Asking delegate to thaw renderers"; delegate_->ThawRenderers(base::Bind(&RendererFreezer::OnThawRenderersComplete, weak_factory_.GetWeakPtr())); } @@ -138,8 +130,6 @@ } void RendererFreezer::OnThawRenderersComplete(bool success) { - // TODO(derat): Remove after http://crbug.com/648580 is fixed. - VLOG(1) << "Thawing renderers complete"; if (success) return;
diff --git a/chrome/browser/chromeos/printer_detector/printer_detector.cc b/chrome/browser/chromeos/printer_detector/printer_detector.cc index 0365914..0409d5c9 100644 --- a/chrome/browser/chromeos/printer_detector/printer_detector.cc +++ b/chrome/browser/chromeos/printer_detector/printer_detector.cc
@@ -26,7 +26,7 @@ #include "chrome/grit/theme_resources.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" -#include "device/core/device_client.h" +#include "device/base/device_client.h" #include "device/usb/usb_device.h" #include "device/usb/usb_device_filter.h" #include "device/usb/usb_ids.h"
diff --git a/chrome/browser/chromeos/printer_detector/printer_detector_unittest.cc b/chrome/browser/chromeos/printer_detector/printer_detector_unittest.cc index da964c9c..6852b00 100644 --- a/chrome/browser/chromeos/printer_detector/printer_detector_unittest.cc +++ b/chrome/browser/chromeos/printer_detector/printer_detector_unittest.cc
@@ -23,7 +23,7 @@ #include "chrome/test/base/testing_profile.h" #include "components/user_manager/fake_user_manager.h" #include "content/public/test/test_browser_thread_bundle.h" -#include "device/core/mock_device_client.h" +#include "device/base/mock_device_client.h" #include "device/usb/mock_usb_device.h" #include "device/usb/mock_usb_service.h" #include "device/usb/usb_descriptors.h"
diff --git a/chrome/browser/chromeos/settings/cros_settings.cc b/chrome/browser/chromeos/settings/cros_settings.cc index c0d7f889..f0a8e71 100644 --- a/chrome/browser/chromeos/settings/cros_settings.cc +++ b/chrome/browser/chromeos/settings/cros_settings.cc
@@ -152,7 +152,8 @@ const base::Value* old_value = GetPref(path); std::unique_ptr<base::Value> new_value(old_value ? old_value->DeepCopy() : new base::ListValue()); - static_cast<base::ListValue*>(new_value.get())->Append(value->DeepCopy()); + static_cast<base::ListValue*>(new_value.get()) + ->Append(value->CreateDeepCopy()); Set(path, *new_value); }
diff --git a/chrome/browser/chromeos/settings/cros_settings_unittest.cc b/chrome/browser/chromeos/settings/cros_settings_unittest.cc index 7fdf021..58bb9203 100644 --- a/chrome/browser/chromeos/settings/cros_settings_unittest.cc +++ b/chrome/browser/chromeos/settings/cros_settings_unittest.cc
@@ -133,7 +133,7 @@ TEST_F(CrosSettingsTest, SetWhitelistWithListOps) { base::ListValue* whitelist = new base::ListValue(); base::StringValue hacky_user("h@xxor"); - whitelist->Append(hacky_user.DeepCopy()); + whitelist->Append(hacky_user.CreateDeepCopy()); AddExpectation(kAccountsPrefAllowNewUser, new base::FundamentalValue(false)); AddExpectation(kAccountsPrefUsers, whitelist); // Add some user to the whitelist. @@ -146,9 +146,9 @@ base::ListValue whitelist; base::StringValue hacky_user("h@xxor"); base::StringValue lamy_user("l@mer"); - whitelist.Append(hacky_user.DeepCopy()); + whitelist.Append(hacky_user.CreateDeepCopy()); base::ListValue* expected_list = whitelist.DeepCopy(); - whitelist.Append(lamy_user.DeepCopy()); + whitelist.Append(lamy_user.CreateDeepCopy()); AddExpectation(kAccountsPrefAllowNewUser, new base::FundamentalValue(false)); AddExpectation(kAccountsPrefUsers, whitelist.DeepCopy()); SetPref(kAccountsPrefUsers, &whitelist);
diff --git a/chrome/browser/chromeos/settings/device_settings_service.cc b/chrome/browser/chromeos/settings/device_settings_service.cc index 993729b..65b148c 100644 --- a/chrome/browser/chromeos/settings/device_settings_service.cc +++ b/chrome/browser/chromeos/settings/device_settings_service.cc
@@ -81,7 +81,8 @@ DeviceSettingsService::~DeviceSettingsService() { DCHECK(pending_operations_.empty()); - FOR_EACH_OBSERVER(Observer, observers_, OnDeviceSettingsServiceShutdown()); + for (auto& observer : observers_) + observer.OnDeviceSettingsServiceShutdown(); } void DeviceSettingsService::SetSessionManager( @@ -281,14 +282,16 @@ } if (new_owner_key) { - FOR_EACH_OBSERVER(Observer, observers_, OwnershipStatusChanged()); + for (auto& observer : observers_) + observer.OwnershipStatusChanged(); content::NotificationService::current()->Notify( chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED, content::Source<DeviceSettingsService>(this), content::NotificationService::NoDetails()); } - FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated()); + for (auto& observer : observers_) + observer.DeviceSettingsUpdated(); std::vector<OwnershipStatusCallback> callbacks; callbacks.swap(pending_ownership_status_callbacks_); @@ -315,7 +318,8 @@ LOG(ERROR) << "Session manager operation failed: " << status; - FOR_EACH_OBSERVER(Observer, observers_, DeviceSettingsUpdated()); + for (auto& observer : observers_) + observer.DeviceSettingsUpdated(); // The completion callback happens after the notification so clients can // filter self-triggered updates.
diff --git a/chrome/browser/chromeos/system/automatic_reboot_manager.cc b/chrome/browser/chromeos/system/automatic_reboot_manager.cc index 08f5aac..c5359a0 100644 --- a/chrome/browser/chromeos/system/automatic_reboot_manager.cc +++ b/chrome/browser/chromeos/system/automatic_reboot_manager.cc
@@ -200,9 +200,8 @@ } AutomaticRebootManager::~AutomaticRebootManager() { - FOR_EACH_OBSERVER(AutomaticRebootManagerObserver, - observers_, - WillDestroyAutomaticRebootManager()); + for (auto& observer : observers_) + observer.WillDestroyAutomaticRebootManager(); DBusThreadManager* dbus_thread_manager = DBusThreadManager::Get(); dbus_thread_manager->GetPowerManagerClient()->RemoveObserver(this); @@ -384,9 +383,8 @@ reboot_requested_ = true; DCHECK_NE(AutomaticRebootManagerObserver::REBOOT_REASON_UNKNOWN, reboot_reason_); - FOR_EACH_OBSERVER(AutomaticRebootManagerObserver, - observers_, - OnRebootRequested(reboot_reason_)); + for (auto& observer : observers_) + observer.OnRebootRequested(reboot_reason_); MaybeReboot(false); }
diff --git a/chrome/browser/chromeos/system/device_disabling_manager.cc b/chrome/browser/chromeos/system/device_disabling_manager.cc index 61d911b..dce9e67 100644 --- a/chrome/browser/chromeos/system/device_disabling_manager.cc +++ b/chrome/browser/chromeos/system/device_disabling_manager.cc
@@ -83,9 +83,8 @@ return; disabled_message_ = disabled_message; - FOR_EACH_OBSERVER(Observer, - observers_, - OnDisabledMessageChanged(disabled_message_)); + for (auto& observer : observers_) + observer.OnDisabledMessageChanged(disabled_message_); } void DeviceDisablingManager::CheckWhetherDeviceDisabledDuringOOBE(
diff --git a/chrome/browser/chromeos/system/pointer_device_observer.cc b/chrome/browser/chromeos/system/pointer_device_observer.cc index c155746..a25aee7 100644 --- a/chrome/browser/chromeos/system/pointer_device_observer.cc +++ b/chrome/browser/chromeos/system/pointer_device_observer.cc
@@ -61,11 +61,13 @@ } void PointerDeviceObserver::OnTouchpadExists(bool exists) { - FOR_EACH_OBSERVER(Observer, observers_, TouchpadExists(exists)); + for (auto& observer : observers_) + observer.TouchpadExists(exists); } void PointerDeviceObserver::OnMouseExists(bool exists) { - FOR_EACH_OBSERVER(Observer, observers_, MouseExists(exists)); + for (auto& observer : observers_) + observer.MouseExists(exists); } PointerDeviceObserver::Observer::~Observer() {
diff --git a/chrome/browser/chromeos/system/system_clock.cc b/chrome/browser/chromeos/system/system_clock.cc index 3264e37..2a300bd 100644 --- a/chrome/browser/chromeos/system/system_clock.cc +++ b/chrome/browser/chromeos/system/system_clock.cc
@@ -212,8 +212,8 @@ // a local owner. if (user_manager::UserManager::Get()->IsCurrentUserOwner()) SetShouldUse24HourClock(ShouldUse24HourClock()); - FOR_EACH_OBSERVER(SystemClockObserver, observer_list_, - OnSystemClockChanged(this)); + for (auto& observer : observer_list_) + observer.OnSystemClockChanged(this); } } // namespace system
diff --git a/chrome/browser/content_settings/local_shared_objects_container.cc b/chrome/browser/content_settings/local_shared_objects_container.cc index 63dabf3..de5a4a2 100644 --- a/chrome/browser/content_settings/local_shared_objects_container.cc +++ b/chrome/browser/content_settings/local_shared_objects_container.cc
@@ -220,7 +220,7 @@ LocalDataContainer* container = new LocalDataContainer( cookies_, databases_, local_storages_, session_storages_, appcaches_, indexed_dbs_, file_systems_, nullptr, channel_ids_, service_workers_, - cache_storages_, nullptr); + cache_storages_, nullptr, nullptr); return base::MakeUnique<CookiesTreeModel>(container, nullptr); }
diff --git a/chrome/browser/devtools/device/usb/android_usb_browsertest.cc b/chrome/browser/devtools/device/usb/android_usb_browsertest.cc index 9878fa1..3867c4d 100644 --- a/chrome/browser/devtools/device/usb/android_usb_browsertest.cc +++ b/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
@@ -22,7 +22,7 @@ #include "chrome/test/base/in_process_browser_test.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/test_utils.h" -#include "device/core/device_client.h" +#include "device/base/device_client.h" #include "device/usb/mock_usb_service.h" #include "device/usb/usb_descriptors.h" #include "device/usb/usb_device.h"
diff --git a/chrome/browser/devtools/device/usb/android_usb_device.cc b/chrome/browser/devtools/device/usb/android_usb_device.cc index 046391a..6ccee19e 100644 --- a/chrome/browser/devtools/device/usb/android_usb_device.cc +++ b/chrome/browser/devtools/device/usb/android_usb_device.cc
@@ -21,7 +21,7 @@ #include "chrome/browser/devtools/device/usb/android_usb_socket.h" #include "content/public/browser/browser_thread.h" #include "crypto/rsa_private_key.h" -#include "device/core/device_client.h" +#include "device/base/device_client.h" #include "device/usb/usb_descriptors.h" #include "device/usb/usb_device.h" #include "device/usb/usb_service.h"
diff --git a/chrome/browser/extensions/api/device_permissions_manager_unittest.cc b/chrome/browser/extensions/api/device_permissions_manager_unittest.cc index eacf06e..6ff4e53 100644 --- a/chrome/browser/extensions/api/device_permissions_manager_unittest.cc +++ b/chrome/browser/extensions/api/device_permissions_manager_unittest.cc
@@ -10,7 +10,7 @@ #include "build/build_config.h" #include "chrome/browser/extensions/test_extension_environment.h" #include "chrome/test/base/testing_profile.h" -#include "device/core/mock_device_client.h" +#include "device/base/mock_device_client.h" #include "device/hid/hid_device_info.h" #include "device/hid/mock_hid_service.h" #include "device/usb/mock_usb_device.h"
diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc index bf6a85b..bbf17ca5 100644 --- a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc +++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc
@@ -264,8 +264,7 @@ std::unique_ptr<base::ListValue> args(new base::ListValue); args->Append(StringToBinaryValue("PAYLOAD")); args->Append(StringToBinaryValue("KEY")); - base::DictionaryValue* options = new base::DictionaryValue(); - args->Append(options); + auto options = base::MakeUnique<base::DictionaryValue>(); options->Set("associatedData", StringToBinaryValue("ASSOCIATED_DATA")); options->Set("publicMetadata", StringToBinaryValue("PUBLIC_METADATA")); options->Set("verificationKeyId", @@ -278,6 +277,7 @@ options->SetString( "signType", api::ToString(api::SIGNATURE_TYPE_HMAC_SHA256)); + args->Append(std::move(options)); ASSERT_TRUE(extension_function_test_utils::RunFunction( function.get(), std::move(args), browser(), @@ -338,8 +338,7 @@ std::unique_ptr<base::ListValue> args(new base::ListValue); args->Append(StringToBinaryValue("PAYLOAD")); args->Append(StringToBinaryValue("KEY")); - base::DictionaryValue* options = new base::DictionaryValue(); - args->Append(options); + auto options = base::MakeUnique<base::DictionaryValue>(); options->Set("associatedData", StringToBinaryValue("ASSOCIATED_DATA")); options->Set("verificationKeyId", @@ -347,6 +346,7 @@ options->SetString( "signType", api::ToString(api::SIGNATURE_TYPE_ECDSA_P256_SHA256)); + args->Append(std::move(options)); ASSERT_TRUE(extension_function_test_utils::RunFunction( function.get(), std::move(args), browser(), @@ -376,8 +376,7 @@ std::unique_ptr<base::ListValue> args(new base::ListValue); args->Append(StringToBinaryValue("MESSAGE")); args->Append(StringToBinaryValue("KEY")); - base::DictionaryValue* options = new base::DictionaryValue(); - args->Append(options); + auto options = base::MakeUnique<base::DictionaryValue>(); options->Set("associatedData", StringToBinaryValue("ASSOCIATED_DATA")); options->SetString( "encryptType", @@ -385,6 +384,7 @@ options->SetString( "signType", api::ToString(api::SIGNATURE_TYPE_HMAC_SHA256)); + args->Append(std::move(options)); ASSERT_TRUE(extension_function_test_utils::RunFunction( function.get(), std::move(args), browser(), @@ -444,13 +444,13 @@ std::unique_ptr<base::ListValue> args(new base::ListValue); args->Append(StringToBinaryValue("MESSAGE")); args->Append(StringToBinaryValue("KEY")); - base::DictionaryValue* options = new base::DictionaryValue(); - args->Append(options); + auto options = base::MakeUnique<base::DictionaryValue>(); options->Set("associatedData", StringToBinaryValue("ASSOCIATED_DATA")); options->SetString( "signType", api::ToString(api::SIGNATURE_TYPE_ECDSA_P256_SHA256)); + args->Append(std::move(options)); ASSERT_TRUE(extension_function_test_utils::RunFunction( function.get(), std::move(args), browser(),
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc index 6069e11..4f1d60f 100644 --- a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc +++ b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
@@ -180,7 +180,7 @@ // first composition character, so for backward compatibility, add it here. base::Value* first_value = NULL; if (bounds_list->Get(0, &first_value)) - args->Append(first_value->DeepCopy()); + args->Append(first_value->CreateDeepCopy()); args->Append(std::move(bounds_list)); DispatchEventToExtension(
diff --git a/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc b/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc index 227a38e0d..4d6598d9 100644 --- a/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc +++ b/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc
@@ -244,16 +244,15 @@ void LogPrivateAPI::AddEntriesOnUI(std::unique_ptr<base::ListValue> value) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - for (std::set<std::string>::iterator ix = net_internal_watches_.begin(); - ix != net_internal_watches_.end(); ++ix) { + for (const std::string& extension_id : net_internal_watches_) { // Create the event's arguments value. std::unique_ptr<base::ListValue> event_args(new base::ListValue()); - event_args->Append(value->DeepCopy()); + event_args->Append(value->CreateDeepCopy()); std::unique_ptr<Event> event( new Event(::extensions::events::LOG_PRIVATE_ON_CAPTURED_EVENTS, ::events::kOnCapturedEvents, std::move(event_args))); EventRouter::Get(browser_context_) - ->DispatchEventToExtension(*ix, std::move(event)); + ->DispatchEventToExtension(extension_id, std::move(event)); } }
diff --git a/chrome/browser/extensions/api/settings_private/OWNERS b/chrome/browser/extensions/api/settings_private/OWNERS index 057813143..e07a545 100644 --- a/chrome/browser/extensions/api/settings_private/OWNERS +++ b/chrome/browser/extensions/api/settings_private/OWNERS
@@ -1,2 +1,3 @@ michaelpg@chromium.org stevenjb@chromium.org +dbeam@chromium.org
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index e64b8ec..db4e3889 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -75,6 +75,10 @@ // Appearance settings. (*s_whitelist)["extensions.theme.id"] = settings_private::PrefType::PREF_TYPE_STRING; +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) + (*s_whitelist)["extensions.theme.use_system"] = + settings_private::PrefType::PREF_TYPE_BOOLEAN; +#endif (*s_whitelist)["webkit.webprefs.default_fixed_font_size"] = settings_private::PrefType::PREF_TYPE_NUMBER; (*s_whitelist)["webkit.webprefs.default_font_size"] =
diff --git a/chrome/browser/extensions/extension_apitest.cc b/chrome/browser/extensions/extension_apitest.cc index 177ac9bc..ec54e6b 100644 --- a/chrome/browser/extensions/extension_apitest.cc +++ b/chrome/browser/extensions/extension_apitest.cc
@@ -18,6 +18,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/extensions/app_launch_params.h" #include "chrome/browser/ui/extensions/application_launch.h" +#include "chrome/common/extensions/extension_process_policy.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/common/content_switches.h" #include "extensions/browser/api/test/test_api.h" @@ -156,7 +157,7 @@ test_config_->SetString(kTestDataDirectory, net::FilePathToFileURL(test_data_dir_).spec()); test_config_->SetInteger(kTestWebSocketPort, 0); - bool isolate_extensions = true; + bool isolate_extensions = extensions::IsIsolateExtensionsEnabled(); test_config_->SetBoolean(kIsolateExtensions, isolate_extensions); extensions::TestGetConfigFunction::set_test_config_state( test_config_.get());
diff --git a/chrome/browser/media/webrtc/desktop_capture_access_handler.cc b/chrome/browser/media/webrtc/desktop_capture_access_handler.cc index 6dae049a..24abef40 100644 --- a/chrome/browser/media/webrtc/desktop_capture_access_handler.cc +++ b/chrome/browser/media/webrtc/desktop_capture_access_handler.cc
@@ -149,7 +149,7 @@ content::MediaStreamDevices* devices, content::DesktopMediaID media_id, bool capture_audio, - bool mute_system_audio, + bool disable_local_echo, bool display_notification, const base::string16& application_title, const base::string16& registered_extension_name) { @@ -157,8 +157,8 @@ std::unique_ptr<content::MediaStreamUI> ui; DVLOG(2) << __FUNCTION__ << ": media_id " << media_id.ToString() - << ", capture_audio " << capture_audio << ", mute_system_audio " - << mute_system_audio << ", display_notification " + << ", capture_audio " << capture_audio << ", disable_local_echo " + << disable_local_echo << ", display_notification " << display_notification << ", application_title " << application_title << ", extension_name " << registered_extension_name; @@ -168,10 +168,12 @@ content::MEDIA_DESKTOP_VIDEO_CAPTURE, media_id.ToString(), "Screen")); if (capture_audio) { if (media_id.type == content::DesktopMediaID::TYPE_WEB_CONTENTS) { + content::WebContentsMediaCaptureId web_id = media_id.web_contents_id; + web_id.disable_local_echo = disable_local_echo; devices->push_back( content::MediaStreamDevice(content::MEDIA_DESKTOP_AUDIO_CAPTURE, - media_id.ToString(), "Tab audio")); - } else if (mute_system_audio) { + web_id.ToString(), "Tab audio")); + } else if (disable_local_echo) { // Use the special loopback device ID for system audio capture. devices->push_back(content::MediaStreamDevice( content::MEDIA_DESKTOP_AUDIO_CAPTURE, @@ -325,9 +327,9 @@ // Determine if the extension is required to display a notification. const bool display_notification = ShouldDisplayNotification(extension); - ui = GetDevicesForDesktopCapture(&devices, screen_id, capture_audio, true, - display_notification, application_title, - application_title); + ui = GetDevicesForDesktopCapture( + &devices, screen_id, capture_audio, request.disable_local_echo, + display_notification, application_title, application_title); DCHECK(!devices.empty()); } @@ -445,7 +447,8 @@ // Determine if the extension is required to display a notification. const bool display_notification = ShouldDisplayNotification(extension); - ui = GetDevicesForDesktopCapture(&devices, media_id, capture_audio, false, + ui = GetDevicesForDesktopCapture(&devices, media_id, capture_audio, + request.disable_local_echo, display_notification, GetApplicationTitle(web_contents, extension), base::UTF8ToUTF16(original_extension_name));
diff --git a/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc b/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc index 2d95084d..cc56614 100644 --- a/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc +++ b/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc
@@ -136,7 +136,7 @@ : content::MEDIA_DEVICE_VIDEO_CAPTURE; return content::MediaStreamRequest(0, 0, 0, example_url(), false, request_type, audio_id, video_id, - audio_type, video_type); + audio_type, video_type, false); } content::MediaStreamRequest CreateRequest(const std::string& audio_id,
diff --git a/chrome/browser/memory/chrome_memory_coordinator_delegate.cc b/chrome/browser/memory/chrome_memory_coordinator_delegate.cc new file mode 100644 index 0000000..672b203 --- /dev/null +++ b/chrome/browser/memory/chrome_memory_coordinator_delegate.cc
@@ -0,0 +1,34 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/memory/chrome_memory_coordinator_delegate.h" + +#include "base/memory/ptr_util.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/memory/tab_manager.h" + +namespace memory { + +// static +std::unique_ptr<content::MemoryCoordinatorDelegate> +ChromeMemoryCoordinatorDelegate::Create() { + return base::WrapUnique(new ChromeMemoryCoordinatorDelegate); +} + +ChromeMemoryCoordinatorDelegate::ChromeMemoryCoordinatorDelegate() {} + +ChromeMemoryCoordinatorDelegate::~ChromeMemoryCoordinatorDelegate() {} + +bool ChromeMemoryCoordinatorDelegate::CanSuspendBackgroundedRenderer( + int render_process_id) { +#if defined(OS_ANDROID) + // TODO(bashi): Implement + return true; +#else + return g_browser_process->GetTabManager()->CanSuspendBackgroundedRenderer( + render_process_id); +#endif +} + +} // namespace memory
diff --git a/chrome/browser/memory/chrome_memory_coordinator_delegate.h b/chrome/browser/memory/chrome_memory_coordinator_delegate.h new file mode 100644 index 0000000..7efe708 --- /dev/null +++ b/chrome/browser/memory/chrome_memory_coordinator_delegate.h
@@ -0,0 +1,32 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_MEMORY_CHROME_MEMORY_COORDINATOR_DELEGATE_H_ +#define CHROME_BROWSER_MEMORY_CHROME_MEMORY_COORDINATOR_DELEGATE_H_ + +#include "base/memory/weak_ptr.h" +#include "content/public/browser/memory_coordinator_delegate.h" + +namespace memory { + +// A MemoryCoordinatorDelegate which uses TabManager internally. +class ChromeMemoryCoordinatorDelegate + : public content::MemoryCoordinatorDelegate { + public: + static std::unique_ptr<content::MemoryCoordinatorDelegate> Create(); + + ~ChromeMemoryCoordinatorDelegate() override; + + // MemoryCoordinatorDelegate implementation. + bool CanSuspendBackgroundedRenderer(int render_process_id) override; + + private: + ChromeMemoryCoordinatorDelegate(); + + DISALLOW_COPY_AND_ASSIGN(ChromeMemoryCoordinatorDelegate); +}; + +} // namespace memory + +#endif // CHROME_BROWSER_MEMORY_CHROME_MEMORY_COORDINATOR_DELEGATE_H_
diff --git a/chrome/browser/memory/tab_manager.cc b/chrome/browser/memory/tab_manager.cc index 582b2e6..8c53fe7f 100644 --- a/chrome/browser/memory/tab_manager.cc +++ b/chrome/browser/memory/tab_manager.cc
@@ -418,6 +418,23 @@ GetWebContentsData(contents)->SetAutoDiscardableState(state); } +bool TabManager::CanSuspendBackgroundedRenderer(int render_process_id) { + // A renderer can be suspended if it's not playing media. + auto tab_stats = GetUnsortedTabStats(); + for (auto& tab : tab_stats) { + if (tab.child_process_host_id != render_process_id) + continue; + TabStripModel* model; + int index = FindTabStripModelById(tab.tab_contents_id, &model); + if (index == -1) + return false; + WebContents* web_contents = model->GetWebContentsAt(index); + if (IsMediaTab(web_contents)) + return false; + } + return true; +} + // static bool TabManager::CompareTabStats(const TabStats& first, const TabStats& second) {
diff --git a/chrome/browser/memory/tab_manager.h b/chrome/browser/memory/tab_manager.h index e6817827..9dc86df 100644 --- a/chrome/browser/memory/tab_manager.h +++ b/chrome/browser/memory/tab_manager.h
@@ -147,6 +147,9 @@ // Sets/clears the auto-discardable state of the tab. void SetTabAutoDiscardableState(content::WebContents* contents, bool state); + // Returns true when a given renderer can suspend when it is backgrounded. + bool CanSuspendBackgroundedRenderer(int render_process_id); + // Returns true if |first| is considered less desirable to be killed than // |second|. static bool CompareTabStats(const TabStats& first, const TabStats& second);
diff --git a/chrome/browser/memory/tab_manager_browsertest.cc b/chrome/browser/memory/tab_manager_browsertest.cc index 917d57f..e991a32e 100644 --- a/chrome/browser/memory/tab_manager_browsertest.cc +++ b/chrome/browser/memory/tab_manager_browsertest.cc
@@ -22,6 +22,7 @@ #include "chrome/test/base/interactive_test_utils.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" +#include "content/public/browser/render_process_host.h" #include "content/public/common/content_switches.h" #include "content/public/test/test_utils.h" #include "url/gurl.h" @@ -392,6 +393,41 @@ EXPECT_TRUE(tab_manager->DiscardTabImpl()); } +IN_PROC_BROWSER_TEST_F(TabManagerTest, CanSuspendBackgroundedRenderer) { + TabManager* tab_manager = g_browser_process->GetTabManager(); + + // Open 2 tabs, the second one being in the background. + ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIAboutURL)); + ui_test_utils::NavigateToURLWithDisposition( + browser(), GURL(chrome::kChromeUIAboutURL), + WindowOpenDisposition::NEW_BACKGROUND_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); + + auto* tab = browser()->tab_strip_model()->GetWebContentsAt(1); + // Simulate that a video stream is now being captured. + content::MediaStreamDevice fake_media_device( + content::MEDIA_DEVICE_VIDEO_CAPTURE, "fake_media_device", + "fake_media_device"); + content::MediaStreamDevices video_devices(1, fake_media_device); + MediaCaptureDevicesDispatcher* dispatcher = + MediaCaptureDevicesDispatcher::GetInstance(); + dispatcher->SetTestVideoCaptureDevices(video_devices); + std::unique_ptr<content::MediaStreamUI> video_stream_ui = + dispatcher->GetMediaStreamCaptureIndicator()->RegisterMediaStream( + tab, video_devices); + video_stream_ui->OnStarted(base::Closure()); + + // Should not be able to suspend a tab which plays a video. + int render_process_id = tab->GetRenderProcessHost()->GetID(); + ASSERT_FALSE(tab_manager->CanSuspendBackgroundedRenderer(render_process_id)); + + // Remove the video stream. + video_stream_ui.reset(); + + // Should be able to suspend the background tab now. + EXPECT_TRUE(tab_manager->CanSuspendBackgroundedRenderer(render_process_id)); +} + IN_PROC_BROWSER_TEST_F(TabManagerTest, AutoDiscardable) { using content::WindowedNotificationObserver; TabManager* tab_manager = g_browser_process->GetTabManager();
diff --git a/chrome/browser/memory/tab_manager_delegate_chromeos.h b/chrome/browser/memory/tab_manager_delegate_chromeos.h index fe3fd10d..cd6a1014 100644 --- a/chrome/browser/memory/tab_manager_delegate_chromeos.h +++ b/chrome/browser/memory/tab_manager_delegate_chromeos.h
@@ -21,7 +21,6 @@ #include "chrome/browser/memory/tab_stats.h" #include "chrome/browser/ui/browser_list_observer.h" #include "chromeos/dbus/debug_daemon_client.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/common/process.mojom.h" #include "components/arc/instance_holder.h" #include "content/public/browser/notification_observer.h"
diff --git a/chrome/browser/metrics/leak_detector/leak_detector_controller.cc b/chrome/browser/metrics/leak_detector/leak_detector_controller.cc index 2f58c726..9f035062 100644 --- a/chrome/browser/metrics/leak_detector/leak_detector_controller.cc +++ b/chrome/browser/metrics/leak_detector/leak_detector_controller.cc
@@ -7,8 +7,10 @@ #include <algorithm> #include "base/logging.h" +#include "base/memory/weak_ptr.h" #include "base/rand_util.h" #include "base/strings/string_number_conversions.h" +#include "base/sys_info.h" #include "components/metrics/leak_detector/gnu_build_id_reader.h" #include "components/variations/variations_associated_data.h" #include "content/public/browser/browser_thread.h" @@ -150,7 +152,10 @@ browser_process_enable_probability_(0), renderer_process_enable_probability_(0), max_renderer_processes_with_leak_detector_enabled_(0), - num_renderer_processes_with_leak_detector_enabled_(0) { + num_renderer_processes_with_leak_detector_enabled_(0), + enable_collect_memory_usage_step_(true), + waiting_for_collect_memory_usage_step_(false), + weak_ptr_factory_(this) { // Read the build ID once and store it. leak_detector::gnu_build_id_reader::ReadBuildID(&build_id_); @@ -214,6 +219,19 @@ --num_renderer_processes_with_leak_detector_enabled_; } +LeakDetectorController::TotalMemoryGrowthTracker::TotalMemoryGrowthTracker() + : total_usage_kb_(0) {} + +LeakDetectorController::TotalMemoryGrowthTracker::~TotalMemoryGrowthTracker() {} + +bool LeakDetectorController::TotalMemoryGrowthTracker::UpdateSample( + base::ProcessId pid, + int sample, + int* diff) { + total_usage_kb_ += sample; + return false; +} + bool LeakDetectorController::ShouldRandomlyEnableLeakDetectorOnRendererProcess() const { return base::RandDouble() < renderer_process_enable_probability_ && @@ -221,11 +239,52 @@ max_renderer_processes_with_leak_detector_enabled_; } +void LeakDetectorController::OnMemoryDetailCollectionDone(size_t index) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(waiting_for_collect_memory_usage_step_); + waiting_for_collect_memory_usage_step_ = false; + + // The available physical memory must be translated from bytes + // and the total memory usage must be translated from kb. + MemoryLeakReportProto::MemoryUsageInfo mem_info; + mem_info.set_available_ram_mb( + base::SysInfo::AmountOfAvailablePhysicalMemory() / 1024 / 1024); + mem_info.set_chrome_ram_usage_mb( + total_memory_growth_tracker_.total_usage_kb() / 1024); + + // Update all reports that arrived in the meantime. + for (; index < stored_reports_.size(); index++) { + stored_reports_[index].mutable_memory_usage_info()->CopyFrom(mem_info); + } +} + void LeakDetectorController::StoreLeakReports( const std::vector<MemoryLeakReportProto>& reports, MemoryLeakReportProto::ProcessType process_type) { DCHECK(thread_checker_.CalledOnValidThread()); + // Postpone a task of collecting info about the memory usage. + // When the task is done, all reports collected after this point + // will be updated, unless GetLeakReports() gets called first. + if (enable_collect_memory_usage_step_ && + !waiting_for_collect_memory_usage_step_) { + waiting_for_collect_memory_usage_step_ = true; + + total_memory_growth_tracker_.reset(); + + // Idea of using MetricsMemoryDetails is similar as in + // ChromeMetricsServiceClient. However, here generation of histogram data + // is suppressed. + base::Closure callback = + base::Bind(&LeakDetectorController::OnMemoryDetailCollectionDone, + weak_ptr_factory_.GetWeakPtr(), stored_reports_.size()); + + scoped_refptr<MetricsMemoryDetails> details( + new MetricsMemoryDetails(callback, &total_memory_growth_tracker_)); + details->set_generate_histograms(false); + details->StartFetch(); + } + for (const auto& report : reports) { // Store the report and insert stored parameters. stored_reports_.push_back(report);
diff --git a/chrome/browser/metrics/leak_detector/leak_detector_controller.h b/chrome/browser/metrics/leak_detector/leak_detector_controller.h index 6651bb7..6908909 100644 --- a/chrome/browser/metrics/leak_detector/leak_detector_controller.h +++ b/chrome/browser/metrics/leak_detector/leak_detector_controller.h
@@ -12,6 +12,7 @@ #include "base/macros.h" #include "base/threading/thread_checker.h" #include "chrome/browser/metrics/leak_detector/leak_detector_remote_controller.h" +#include "chrome/browser/metrics/metrics_memory_details.h" #include "components/metrics/leak_detector/leak_detector.h" #include "components/metrics/proto/memory_leak_report.pb.h" @@ -40,7 +41,30 @@ const std::vector<MemoryLeakReportProto>& reports) override; void OnRemoteProcessShutdown() override; + void set_enable_collect_memory_usage_step(bool enabled) { + enable_collect_memory_usage_step_ = enabled; + } + private: + // Accumulates total memory usage info inside MetricsMemoryDetails. + class TotalMemoryGrowthTracker : public MemoryGrowthTracker { + public: + TotalMemoryGrowthTracker(); + ~TotalMemoryGrowthTracker() override; + + // Updates the inner counter by sample (in kb). Returns always false + // to suppress generating growth/shrink histograms in MetricsMemoryDetails. + bool UpdateSample(base::ProcessId pid, int sample, int* diff) override; + + size_t total_usage_kb() const { return total_usage_kb_; } + void reset() { total_usage_kb_ = 0; } + + private: + size_t total_usage_kb_; + + DISALLOW_COPY_AND_ASSIGN(TotalMemoryGrowthTracker); + }; + // Returns true to indicate that LeakDetector should be enabled on a renderer // process. This is determined as follows: // 1. If the number of processes running LeakDetector is not at max, returns @@ -55,6 +79,10 @@ void StoreLeakReports(const std::vector<MemoryLeakReportProto>& reports, MemoryLeakReportProto::ProcessType process_type); + // Method called from MetricsMemoryDetails when memory usage gets measured. + // Updates |memory_usage_info| in stored_reports_[i] for i >= |index|. + void OnMemoryDetailCollectionDone(size_t index); + // All leak reports received through OnLeakFound() are stored in protobuf // format. std::vector<MemoryLeakReportProto> stored_reports_; @@ -85,6 +113,19 @@ // For thread safety. base::ThreadChecker thread_checker_; + // An object passed to MetricsMemoryDetails for collecting memory usage. + TotalMemoryGrowthTracker total_memory_growth_tracker_; + + // A flag indicating if a task should be scheduled to populate memory usage + // information in the reports. + bool enable_collect_memory_usage_step_; + + // Indicates that collecting memory usage is running. + bool waiting_for_collect_memory_usage_step_; + + // For passing |this| into a callback. + base::WeakPtrFactory<LeakDetectorController> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(LeakDetectorController); };
diff --git a/chrome/browser/metrics/leak_detector/leak_detector_controller_unittest.cc b/chrome/browser/metrics/leak_detector/leak_detector_controller_unittest.cc index f900f21..a77369a 100644 --- a/chrome/browser/metrics/leak_detector/leak_detector_controller_unittest.cc +++ b/chrome/browser/metrics/leak_detector/leak_detector_controller_unittest.cc
@@ -32,7 +32,10 @@ public: using LeakDetectorController::OnLeaksFound; - TestLeakDetectorController() {} + // This constructor suppresses starting memory metrics job in the superclass. + TestLeakDetectorController() { + LeakDetectorController::set_enable_collect_memory_usage_step(false); + } private: DISALLOW_COPY_AND_ASSIGN(TestLeakDetectorController);
diff --git a/chrome/browser/metrics/metrics_memory_details.cc b/chrome/browser/metrics/metrics_memory_details.cc index f8ccb55..de76fc1 100644 --- a/chrome/browser/metrics/metrics_memory_details.cc +++ b/chrome/browser/metrics/metrics_memory_details.cc
@@ -58,15 +58,17 @@ MetricsMemoryDetails::MetricsMemoryDetails( const base::Closure& callback, MemoryGrowthTracker* memory_growth_tracker) - : callback_(callback), memory_growth_tracker_(memory_growth_tracker) { - memory_growth_tracker_ = memory_growth_tracker; -} + : callback_(callback), + memory_growth_tracker_(memory_growth_tracker), + generate_histograms_(true) {} MetricsMemoryDetails::~MetricsMemoryDetails() { } void MetricsMemoryDetails::OnDetailsAvailable() { - UpdateHistograms(); + if (generate_histograms_) + UpdateHistograms(); + AnalyzeMemoryGrowth(); base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback_); } @@ -120,15 +122,6 @@ sample / 1024); UMA_HISTOGRAM_MEMORY_LARGE_MB("Memory.Renderer.Committed", committed / 1024); - int diff; - if (memory_growth_tracker_ && - memory_growth_tracker_->UpdateSample( - browser.processes[index].pid, sample, &diff)) { - if (diff < 0) - UMA_HISTOGRAM_MEMORY_KB("Memory.RendererShrinkIn30Min", -diff); - else - UMA_HISTOGRAM_MEMORY_KB("Memory.RendererGrowthIn30Min", diff); - } renderer_count++; continue; } @@ -311,3 +304,22 @@ } } #endif // defined(OS_CHROMEOS) + +void MetricsMemoryDetails::AnalyzeMemoryGrowth() { + for (const auto& process_entry : ChromeBrowser()->processes) { + int sample = static_cast<int>(process_entry.working_set.priv); + int diff; + + // UpdateSample changes state of |memory_growth_tracker_| and it should be + // called even if |generate_histograms_| is false. + if (memory_growth_tracker_ && + memory_growth_tracker_->UpdateSample(process_entry.pid, sample, + &diff) && + generate_histograms_) { + if (diff < 0) + UMA_HISTOGRAM_MEMORY_KB("Memory.RendererShrinkIn30Min", -diff); + else + UMA_HISTOGRAM_MEMORY_KB("Memory.RendererGrowthIn30Min", diff); + } + } +}
diff --git a/chrome/browser/metrics/metrics_memory_details.h b/chrome/browser/metrics/metrics_memory_details.h index 23badc56..f833afb 100644 --- a/chrome/browser/metrics/metrics_memory_details.h +++ b/chrome/browser/metrics/metrics_memory_details.h
@@ -17,7 +17,7 @@ class MemoryGrowthTracker { public: MemoryGrowthTracker(); - ~MemoryGrowthTracker(); + virtual ~MemoryGrowthTracker(); // If 30 minutes have passed since last UMA record, UpdateSample() computes // a difference between current memory usage |sample| of process |pid| and @@ -27,7 +27,7 @@ // If no memory usage of |pid| has not been recorded so far or 30 minutes // have not passed since last record, it just returns false. // |sample| is memory usage in kB. - bool UpdateSample(base::ProcessId pid, int sample, int* diff); + virtual bool UpdateSample(base::ProcessId pid, int sample, int* diff); private: // Latest metrics about record time and memory usage at that time per process. @@ -46,6 +46,10 @@ MetricsMemoryDetails(const base::Closure& callback, MemoryGrowthTracker* memory_growth_tracker); + void set_generate_histograms(bool generate_histograms) { + generate_histograms_ = generate_histograms; + } + protected: ~MetricsMemoryDetails() override; @@ -60,6 +64,10 @@ void UpdateSwapHistograms(); #endif + // Notifies |memory_growth_tracker_| about the memory usage. + // Update histograms on memory growth or shrink in renderer processes. + void AnalyzeMemoryGrowth(); + base::Closure callback_; // A pointer to MemoryGrowthTracker which is contained in a longer-lived @@ -67,6 +75,10 @@ // If it is null, nothing is tracked. MemoryGrowthTracker* memory_growth_tracker_; + // A flag indicating if histogram data should be generated. True on default. + // If false, then only MemoryGrowthTracker gets notified about memory usage. + bool generate_histograms_; + DISALLOW_COPY_AND_ASSIGN(MetricsMemoryDetails); };
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc index 48c1759..cf6c889 100644 --- a/chrome/browser/policy/policy_browsertest.cc +++ b/chrome/browser/policy/policy_browsertest.cc
@@ -3253,12 +3253,10 @@ } void FinishAudioTest() { - content::MediaStreamRequest request(0, 0, 0, - request_url_.GetOrigin(), false, - content::MEDIA_DEVICE_ACCESS, - std::string(), std::string(), - content::MEDIA_DEVICE_AUDIO_CAPTURE, - content::MEDIA_NO_SERVICE); + content::MediaStreamRequest request( + 0, 0, 0, request_url_.GetOrigin(), false, content::MEDIA_DEVICE_ACCESS, + std::string(), std::string(), content::MEDIA_DEVICE_AUDIO_CAPTURE, + content::MEDIA_NO_SERVICE, false); // TODO(raymes): Test MEDIA_DEVICE_OPEN (Pepper) which grants both webcam // and microphone permissions at the same time. MediaStreamDevicesController controller( @@ -3272,13 +3270,10 @@ } void FinishVideoTest() { - content::MediaStreamRequest request(0, 0, 0, - request_url_.GetOrigin(), false, - content::MEDIA_DEVICE_ACCESS, - std::string(), - std::string(), - content::MEDIA_NO_SERVICE, - content::MEDIA_DEVICE_VIDEO_CAPTURE); + content::MediaStreamRequest request( + 0, 0, 0, request_url_.GetOrigin(), false, content::MEDIA_DEVICE_ACCESS, + std::string(), std::string(), content::MEDIA_NO_SERVICE, + content::MEDIA_DEVICE_VIDEO_CAPTURE, false); // TODO(raymes): Test MEDIA_DEVICE_OPEN (Pepper) which grants both webcam // and microphone permissions at the same time. MediaStreamDevicesController controller(
diff --git a/chrome/browser/prerender/prerender_manager_factory.h b/chrome/browser/prerender/prerender_manager_factory.h index 46e7e67..c5bc777 100644 --- a/chrome/browser/prerender/prerender_manager_factory.h +++ b/chrome/browser/prerender/prerender_manager_factory.h
@@ -24,7 +24,7 @@ // associated PrerenderManager. class PrerenderManagerFactory : public BrowserContextKeyedServiceFactory { public: - // Returns the PrerenderManager for |profile|. + // Returns the PrerenderManager for |context|. static PrerenderManager* GetForBrowserContext( content::BrowserContext* context);
diff --git a/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js b/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js index 961b15d..b9af7fb9 100644 --- a/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js +++ b/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js
@@ -15,28 +15,22 @@ AdapterClient.prototype = { /** * Prints added device to console. - * @param {!Object} device the device that was added + * @param {!bluetoothDevice.DeviceInfo} device */ - deviceAdded: function(device) { - console.log('Device added'); - console.log(device); - }, + deviceAdded: function(device) { console.log('Device added', device); }, /** * Prints removed device to console. - * @param {!Object} device the device that was removed + * @param {!bluetoothDevice.DeviceInfo} device */ - deviceRemoved: function(device) { - console.log('Device removed'); - console.log(device); - } + deviceRemoved: function(device) { console.log('Device removed', device); } }; (function() { - var adapter, adapterClient; + var adapter, adapterClient, bluetoothAdapter, bluetoothDevice, connection; /** - * TODO: Move to shared location. See http://crbug.com/652361. + * TODO(crbug.com/652361): Move to shared location. * Helper to convert callback-based define() API to a promise-based API. * @param {!Array<string>} moduleNames * @return {!Promise} @@ -58,10 +52,14 @@ return importModules([ 'content/public/renderer/frame_interfaces', 'device/bluetooth/public/interfaces/adapter.mojom', + 'device/bluetooth/public/interfaces/device.mojom', 'mojo/public/js/connection', - ]).then(function([frameInterfaces, bluetoothAdapter, connection]) { + ]).then(function([frameInterfaces, ...modules]) { console.log('Loaded modules'); + // Destructure here to assign global variables. + [bluetoothAdapter, bluetoothDevice, connection] = modules; + // Hook up the instance properties. AdapterClient.prototype.__proto__ = bluetoothAdapter.AdapterClient.stubClass.prototype; @@ -71,28 +69,55 @@ bluetoothAdapter.AdapterFactory); // Get an Adapter service. - return adapterFactory.getAdapter().then(function(response) { - if (!response.adapter) { - throw new Error('Bluetooth Not Supported on this platform.'); - } + return adapterFactory.getAdapter(); + }).then(function(response) { + if (!response.adapter) { + throw new Error('Bluetooth Not Supported on this platform.'); + } - adapter = connection.bindHandleToProxy(response.adapter, - bluetoothAdapter.Adapter); + adapter = connection.bindHandleToProxy(response.adapter, + bluetoothAdapter.Adapter); - // Create a message pipe and bind one end to client - // implementation and the other to the Adapter service. - adapterClient = new AdapterClient(); - adapter.setClient(connection.bindStubDerivedImpl(adapterClient)); - }); + // Create a message pipe and bind one end to client + // implementation and the other to the Adapter service. + adapterClient = new AdapterClient(); + adapter.setClient(connection.bindStubDerivedImpl(adapterClient)); }); } + /** + * Prints device info from the device service. + * @param {!bluetoothDevice.DeviceInfo} deviceInfo the device for which to + * get the information. + * @return {!Promise} resolves if device service is retrieved, rejects + * otherwise. + */ + function logDevice(deviceInfo) { + return adapter.getDevice(deviceInfo.address).then(function(response) { + var deviceHandle = response.device; + if (!deviceHandle) { + throw new Error(deviceInfo.name_for_display + ' cannot be found.'); + } + + var device = connection.bindHandleToProxy( + deviceHandle, bluetoothDevice.Device); + return device.getInfo(); + }).then(function(response) { + console.log(deviceInfo.name_for_display, response.info); + }); + } + document.addEventListener('DOMContentLoaded', function() { initializeProxies() - .then(function() {return adapter.getInfo(); }) - .then(function(response) { console.log('info', response.info); }) + .then(function() { return adapter.getInfo(); }) + .then(function(response) { console.log('adapter', response.info); }) .then(function() { return adapter.getDevices(); }) - .then(function(response) { console.log('devices', response.devices); }) + .then(function(response) { + var devices = response.devices; + console.log('devices', devices.length); + + return Promise.all(devices.map(logDevice)); + }) .catch(function(error) { console.error(error); }); }); })();
diff --git a/chrome/browser/resources/options/cookies_list.js b/chrome/browser/resources/options/cookies_list.js index c3b97c2..21f4d00b 100644 --- a/chrome/browser/resources/options/cookies_list.js +++ b/chrome/browser/resources/options/cookies_list.js
@@ -47,6 +47,9 @@ ['size', 'label_cache_storage_size'], ['modified', 'label_cache_storage_last_modified']], 'flash_lso': [['domain', 'label_cookie_domain']], + 'media_license': [['origin', 'label_media_license_origin'], + ['size', 'label_media_license_size'], + ['modified', 'label_media_license_last_modified']], }; /** @@ -256,6 +259,7 @@ channelIDs: 0, serviceWorker: false, cacheStorage: false, + mediaLicense: false, }; if (this.origin) this.origin.collectSummaryInfo(info); @@ -281,6 +285,8 @@ list.push(loadTimeData.getString('cookie_cache_storage')); if (info.flashLSO) list.push(loadTimeData.getString('cookie_flash_lso')); + if (info.mediaLicense) + list.push(loadTimeData.getString('cookie_media_license')); var text = ''; for (var i = 0; i < list.length; ++i) { @@ -505,6 +511,8 @@ info.cacheStorage = true; } else if (this.data.type == 'flash_lso') { info.flashLSO = true; + } else if (this.data.type == 'media_license') { + info.mediaLicense = true; } var apps = this.data.appsProtectingThis;
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_browser_proxy.js b/chrome/browser/resources/settings/appearance_page/appearance_browser_proxy.js index 8982f69..d5df599 100644 --- a/chrome/browser/resources/settings/appearance_page/appearance_browser_proxy.js +++ b/chrome/browser/resources/settings/appearance_page/appearance_browser_proxy.js
@@ -8,15 +8,20 @@ AppearanceBrowserProxy.prototype = { /** - * @return {!Promise<boolean>} Whether the theme may be reset. + * @param {string} themeId + * @return {!Promise<!chrome.management.ExtensionInfo>} Theme info. */ - getResetThemeEnabled: assertNotReached, + getThemeInfo: assertNotReached, <if expr="chromeos"> openWallpaperManager: assertNotReached, </if> - resetTheme: assertNotReached, + useDefaultTheme: assertNotReached, + +<if expr="is_linux and not chromeos"> + useSystemTheme: assertNotReached, +</if> }; /** @@ -29,8 +34,10 @@ AppearanceBrowserProxyImpl.prototype = { /** @override */ - getResetThemeEnabled: function() { - return cr.sendWithPromise('getResetThemeEnabled'); + getThemeInfo: function(themeId) { + return new Promise(function(resolve) { + chrome.management.get(themeId, resolve); + }); }, <if expr="chromeos"> @@ -41,9 +48,16 @@ </if> /** @override */ - resetTheme: function() { - chrome.send('resetTheme'); + useDefaultTheme: function() { + chrome.send('useDefaultTheme'); }, + +<if expr="is_linux and not chromeos"> + /** @override */ + useSystemTheme: function() { + chrome.send('useSystemTheme'); + }, +</if> }; return {
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.html b/chrome/browser/resources/settings/appearance_page/appearance_page.html index e854d240..82d49c3 100644 --- a/chrome/browser/resources/settings/appearance_page/appearance_page.html +++ b/chrome/browser/resources/settings/appearance_page/appearance_page.html
@@ -24,6 +24,10 @@ font-weight: inherit; }; } + + .secondary-button ~ .secondary-button { + -webkit-margin-start: 12px; + } </style> <settings-animated-pages id="pages" section="appearance"> <neon-animatable route-path="default"> @@ -38,27 +42,47 @@ <button class="icon-external" is="paper-icon-button-light"></button> </div> <div class="settings-box two-line" - hidden="[[!pageVisibility.setTheme]]" actionable> + hidden="[[!pageVisibility.setTheme]]"> </if> <if expr="not chromeos"> <div class="settings-box two-line first" - hidden="[[!pageVisibility.setTheme]]" actionable> + hidden="[[!pageVisibility.setTheme]]"> </if> - <div class="start two-line" on-tap="openThemesGallery_"> + <div class="start two-line" on-tap="onThemesTap_" actionable> <div class="flex"> - <div>$i18n{theme}</div> + <div>$i18n{themes}</div> <div class="secondary">[[themeSublabel_]]</div> </div> <button class="icon-external" is="paper-icon-button-light"></button> </div> - <template is="dom-if" if="[[allowResetTheme_]]"> +<if expr="not is_linux or chromeos"> + <template is="dom-if" if="[[prefs.extensions.theme.id.value]]"> <div class="secondary-action"> - <paper-button id="resetTheme" on-tap="resetTheme_" + <paper-button id="useDefault" on-tap="onUseDefaultTap_" class="secondary-button"> $i18n{resetToDefaultTheme} </paper-button> </div> </template> +</if> +<if expr="is_linux and not chromeos"> + <div class="secondary-action"> + <template is="dom-if" if="[[showUseClassic_( + prefs.extensions.theme.id.value, useSystemTheme_)]]" restamp> + <paper-button id="useDefault" on-tap="onUseDefaultTap_" + class="secondary-button"> + $i18n{useClassicTheme} + </paper-button> + </template> + <template is="dom-if" if="[[showUseSystem_( + prefs.extensions.theme.id.value, useSystemTheme_)]]" restamp> + <paper-button id="useSystem" on-tap="onUseSystemTap_" + class="secondary-button"> + $i18n{useSystemTheme} + </paper-button> + </template> + </div> +</if> </div> <div class="settings-box" hidden="[[!pageVisibility.homeButton]]">
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.js b/chrome/browser/resources/settings/appearance_page/appearance_page.js index 5b7462b..7e0661d 100644 --- a/chrome/browser/resources/settings/appearance_page/appearance_page.js +++ b/chrome/browser/resources/settings/appearance_page/appearance_page.js
@@ -23,26 +23,18 @@ /** @private {!settings.AppearanceBrowserProxy} */ browserProxy_: Object, - /** - * Preferences state. - */ prefs: { type: Object, notify: true, }, - /** - * @private - */ - allowResetTheme_: { - notify: true, + /** @private */ + useSystemTheme_: { type: Boolean, - value: false, + value: false, // Can only be true on Linux, but value exists everywhere. }, - /** - * @private - */ + /** @private */ defaultZoomLevel_: { notify: true, type: Object, @@ -109,8 +101,17 @@ pageVisibility: Object, }, + /** @private {string} */ + themeUrl_: '', + observers: [ - 'themeChanged_(prefs.extensions.theme.id.value)', + 'themeChanged_(prefs.extensions.theme.id.value, useSystemTheme_)', + +<if expr="is_linux and not chromeos"> + // NOTE: this pref only exists on Linux. + 'useSystemThemePrefChanged_(prefs.extensions.theme.use_system.value)', +</if> + 'zoomLevelChanged_(defaultZoomLevel_.value)', ], @@ -127,17 +128,6 @@ this.zoomPrefChanged_.bind(this)); }, - /** @override */ - attached: function() { - // Query the initial state. - this.browserProxy_.getResetThemeEnabled().then( - this.setResetThemeEnabled.bind(this)); - - // Set up the change event listener. - cr.addWebUIListener('reset-theme-enabled-changed', - this.setResetThemeEnabled.bind(this)); - }, - /** * @param {boolean} isNtp Whether to use the NTP as the home page. * @param {string} homepage If not using NTP, use this URL. @@ -150,21 +140,14 @@ return homepage || this.i18n('exampleDotCom'); }, - /** - * @param {boolean} enabled Whether the theme reset is available. - */ - setResetThemeEnabled: function(enabled) { - this.allowResetTheme_ = enabled; - }, - /** @private */ onCustomizeFontsTap_: function() { settings.navigateTo(settings.Route.FONTS); }, /** @private */ - openThemesGallery_: function() { - window.open(loadTimeData.getString('themesGalleryUrl')); + onThemesTap_: function() { + window.open(this.themeUrl_ || loadTimeData.getString('themesGalleryUrl')); }, <if expr="chromeos"> @@ -178,23 +161,71 @@ </if> /** @private */ - resetTheme_: function() { - this.browserProxy_.resetTheme(); + onUseDefaultTap_: function() { + this.browserProxy_.useDefaultTheme(); + }, + +<if expr="is_linux and not chromeos"> + /** + * @param {boolean} useSystemTheme + * @private + */ + useSystemThemePrefChanged_: function(useSystemTheme) { + this.useSystemTheme_ = useSystemTheme; }, /** - * @param {string} themeId The theme ID. + * @param {string} themeId + * @param {boolean} useSystemTheme + * @return {boolean} Whether to show the "USE CLASSIC" button. * @private */ - themeChanged_: function(themeId) { + showUseClassic_: function(themeId, useSystemTheme) { + return !!themeId || useSystemTheme; + }, + + /** + * @param {string} themeId + * @param {boolean} useSystemTheme + * @return {boolean} Whether to show the "USE GTK+" button. + * @private + */ + showUseSystem_: function(themeId, useSystemTheme) { + return !!themeId || !useSystemTheme; + }, + + /** @private */ + onUseSystemTap_: function() { + this.browserProxy_.useSystemTheme(); + }, +</if> + + /** + * @param {string} themeId + * @param {boolean} useSystemTheme + * @private + */ + themeChanged_: function(themeId, useSystemTheme) { if (themeId) { - chrome.management.get(themeId, - function(info) { - this.themeSublabel_ = info.name; - }.bind(this)); - } else { - this.themeSublabel_ = this.i18n('chooseFromWebStore'); + assert(!useSystemTheme); + + this.browserProxy_.getThemeInfo(themeId).then(function(info) { + this.themeSublabel_ = info.name; + }.bind(this)); + + this.themeUrl_ = `https://chrome.google.com/webstore/detail/${themeId}`; + return; } + + var i18nId; +<if expr="is_linux and not chromeos"> + i18nId = useSystemTheme ? 'systemTheme' : 'classicTheme'; +</if> +<if expr="not is_linux or chromeos"> + i18nId = 'chooseFromWebStore'; +</if> + this.themeSublabel_ = this.i18n(i18nId); + this.themeUrl_ = ''; }, /**
diff --git a/chrome/browser/resources/settings/appearance_page/compiled_resources2.gyp b/chrome/browser/resources/settings/appearance_page/compiled_resources2.gyp index 29c7905..2f218e8 100644 --- a/chrome/browser/resources/settings/appearance_page/compiled_resources2.gyp +++ b/chrome/browser/resources/settings/appearance_page/compiled_resources2.gyp
@@ -21,6 +21,7 @@ 'dependencies': [ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', + '<(EXTERNS_GYP):management', '<(EXTERNS_GYP):chrome_send', ], 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], @@ -31,7 +32,6 @@ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data', - '<(EXTERNS_GYP):management', '<(EXTERNS_GYP):settings_private', '<(EXTERNS_GYP):chrome_send', '../compiled_resources2.gyp:route',
diff --git a/chrome/browser/resources/settings/site_settings/cookie_info.js b/chrome/browser/resources/settings/site_settings/cookie_info.js index 3b912a3..f78e161f2 100644 --- a/chrome/browser/resources/settings/site_settings/cookie_info.js +++ b/chrome/browser/resources/settings/site_settings/cookie_info.js
@@ -45,4 +45,7 @@ ['size', 'cacheStorageSize'], ['modified', 'cacheStorageLastModified']], 'flash_lso': [['domain', 'cookieDomain']], + 'media_license': [['origin', 'mediaLicenseOrigin'], + ['size', 'mediaLicenseSize'], + ['modified', 'mediaLicenseLastModified']], };
diff --git a/chrome/browser/resources/settings/site_settings/cookie_tree_node.js b/chrome/browser/resources/settings/site_settings/cookie_tree_node.js index 61dacf91..cfb0662 100644 --- a/chrome/browser/resources/settings/site_settings/cookie_tree_node.js +++ b/chrome/browser/resources/settings/site_settings/cookie_tree_node.js
@@ -56,6 +56,7 @@ 'indexed_db': loadTimeData.getString('cookieDatabaseStorage'), 'local_storage': loadTimeData.getString('cookieLocalStorage'), 'service_worker': loadTimeData.getString('cookieServiceWorker'), + 'media_license': loadTimeData.getString('cookieMediaLicense'), }; /**
diff --git a/chrome/browser/ssl/chrome_security_state_model_client.cc b/chrome/browser/ssl/chrome_security_state_model_client.cc index 51cd505..8f5d3232 100644 --- a/chrome/browser/ssl/chrome_security_state_model_client.cc +++ b/chrome/browser/ssl/chrome_security_state_model_client.cc
@@ -82,12 +82,12 @@ const char* cipher; const char* mac; bool is_aead; + bool is_tls13; uint16_t cipher_suite = net::SSLConnectionStatusToCipherSuite(security_info.connection_status); net::SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, - cipher_suite); + &is_tls13, cipher_suite); base::string16 protocol_name = base::ASCIIToUTF16(protocol); - base::string16 key_exchange_name = base::ASCIIToUTF16(key_exchange); const base::string16 cipher_name = (mac == NULL) ? base::ASCIIToUTF16(cipher) : l10n_util::GetStringFUTF16(IDS_CIPHER_WITH_MAC, @@ -95,15 +95,17 @@ base::ASCIIToUTF16(mac)); // Include the key exchange group (previously known as curve) if specified. - // - // TODO(davidben): When TLS 1.3's new negotiation is implemented, omit the - // "key exchange" if empty and only display the group, which is the true key - // exchange. See https://crbug.com/639495. - if (security_info.key_exchange_group != 0) { + base::string16 key_exchange_name; + if (is_tls13) { + key_exchange_name = base::ASCIIToUTF16( + SSL_get_curve_name(security_info.key_exchange_group)); + } else if (security_info.key_exchange_group != 0) { key_exchange_name = l10n_util::GetStringFUTF16( - IDS_SSL_KEY_EXCHANGE_WITH_GROUP, key_exchange_name, + IDS_SSL_KEY_EXCHANGE_WITH_GROUP, base::ASCIIToUTF16(key_exchange), base::ASCIIToUTF16( SSL_get_curve_name(security_info.key_exchange_group))); + } else { + key_exchange_name = base::ASCIIToUTF16(key_exchange); } if (security_info.obsolete_ssl_status == net::OBSOLETE_SSL_NONE) {
diff --git a/chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc b/chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc index 2b2cff2..daeaafb 100644 --- a/chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc +++ b/chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc
@@ -177,13 +177,14 @@ int ssl_version = net::SSLConnectionStatusToVersion(security_info.connection_status); net::SSLVersionToString(&protocol, ssl_version); - bool is_aead; + bool is_aead, is_tls13; uint16_t cipher_suite = net::SSLConnectionStatusToCipherSuite(security_info.connection_status); net::SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, - cipher_suite); + &is_tls13, cipher_suite); EXPECT_TRUE(is_aead); - EXPECT_EQ(NULL, mac); // The default secure cipher does not have a MAC. + EXPECT_EQ(nullptr, mac); // The default secure cipher does not have a MAC. + EXPECT_FALSE(is_tls13); // The default secure cipher is not TLS 1.3. base::string16 key_exchange_name = base::ASCIIToUTF16(key_exchange); if (security_info.key_exchange_group != 0) {
diff --git a/chrome/browser/ssl/chrome_security_state_model_client_unittest.cc b/chrome/browser/ssl/chrome_security_state_model_client_unittest.cc index 3f6ed9d..3e9333644 100644 --- a/chrome/browser/ssl/chrome_security_state_model_client_unittest.cc +++ b/chrome/browser/ssl/chrome_security_state_model_client_unittest.cc
@@ -191,6 +191,26 @@ "strong cipher (CHACHA20_POLY1305).", explanation.description); } + + // TLS 1.3 ciphers use the key exchange group exclusively. + net::SSLConnectionStatusSetCipherSuite(0x1301 /* TLS_AES_128_GCM_SHA256 */, + &security_info.connection_status); + net::SSLConnectionStatusSetVersion(net::SSL_CONNECTION_VERSION_TLS1_3, + &security_info.connection_status); + security_info.key_exchange_group = 29; // X25519 + { + content::SecurityStyleExplanations explanations; + ChromeSecurityStateModelClient::GetSecurityStyle(security_info, + &explanations); + content::SecurityStyleExplanation explanation; + ASSERT_TRUE(FindSecurityStyleExplanation( + explanations.secure_explanations, "Secure Connection", &explanation)); + EXPECT_EQ( + "The connection to this site is encrypted and authenticated using a " + "strong protocol (TLS 1.3), a strong key exchange (X25519), and a " + "strong cipher (AES_128_GCM).", + explanation.description); + } } } // namespace
diff --git a/chrome/browser/sync/test/integration/two_client_uss_sync_test.cc b/chrome/browser/sync/test/integration/two_client_uss_sync_test.cc index 9035d31b..29aa0b8 100644 --- a/chrome/browser/sync/test/integration/two_client_uss_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_uss_sync_test.cc
@@ -57,7 +57,10 @@ }; TestModelTypeService() - : FakeModelTypeService(base::Bind(&ModelTypeChangeProcessor::Create)) {} + : FakeModelTypeService(base::Bind(&ModelTypeChangeProcessor::Create)) { + change_processor()->OnMetadataLoaded(syncer::SyncError(), + db().CreateMetadataBatch()); + } syncer::SyncError ApplySyncChanges( std::unique_ptr<syncer::MetadataChangeList> metadata_changes, @@ -68,11 +71,6 @@ return error; } - void OnChangeProcessorSet() override { - change_processor()->OnMetadataLoaded(syncer::SyncError(), - db().CreateMetadataBatch()); - } - void AddObserver(Observer* observer) { observers_.insert(observer); } void RemoveObserver(Observer* observer) { observers_.erase(observer); }
diff --git a/chrome/browser/task_manager/providers/arc/arc_process_task.cc b/chrome/browser/task_manager/providers/arc/arc_process_task.cc index 1f0b4fe..b664ec71 100644 --- a/chrome/browser/task_manager/providers/arc/arc_process_task.cc +++ b/chrome/browser/task_manager/providers/arc/arc_process_task.cc
@@ -9,6 +9,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "chrome/grit/generated_resources.h" +#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service_manager.h" #include "components/arc/common/process.mojom.h" #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/task_manager/providers/arc/arc_process_task.h b/chrome/browser/task_manager/providers/arc/arc_process_task.h index 6fce2edb..85d86ab1b 100644 --- a/chrome/browser/task_manager/providers/arc/arc_process_task.h +++ b/chrome/browser/task_manager/providers/arc/arc_process_task.h
@@ -12,7 +12,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/task_manager/providers/task.h" -#include "components/arc/arc_bridge_service.h" +#include "components/arc/common/intent_helper.mojom.h" #include "components/arc/common/process.mojom.h" #include "components/arc/instance_holder.h" #include "components/arc/intent_helper/activity_icon_loader.h"
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 58908ae..8db1c6f 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -559,8 +559,8 @@ "//content/app/resources", "//content/public/common", "//crypto", + "//device/base", "//device/bluetooth/public/interfaces:experimental_interfaces", - "//device/core", "//device/usb", "//media", "//net:net_with_v8",
diff --git a/chrome/browser/ui/android/ssl_client_certificate_request.cc b/chrome/browser/ui/android/ssl_client_certificate_request.cc index b8bdd44..b9bdd71 100644 --- a/chrome/browser/ui/android/ssl_client_certificate_request.cc +++ b/chrome/browser/ui/android/ssl_client_certificate_request.cc
@@ -160,7 +160,7 @@ // Create an SSLPrivateKey wrapper for the private key JNI reference. scoped_refptr<net::SSLPrivateKey> private_key = - net::WrapJavaPrivateKey(private_key_ref); + net::WrapJavaPrivateKey(client_cert.get(), private_key_ref); if (!private_key) { LOG(ERROR) << "Could not create OpenSSL wrapper for private key"; return;
diff --git a/chrome/browser/ui/android/usb_chooser_dialog_android.cc b/chrome/browser/ui/android/usb_chooser_dialog_android.cc index 82d5336..e6e15359 100644 --- a/chrome/browser/ui/android/usb_chooser_dialog_android.cc +++ b/chrome/browser/ui/android/usb_chooser_dialog_android.cc
@@ -22,7 +22,7 @@ #include "content/public/browser/android/content_view_core.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" -#include "device/core/device_client.h" +#include "device/base/device_client.h" #include "device/usb/mojo/type_converters.h" #include "device/usb/usb_device.h" #include "device/usb/usb_device_filter.h"
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.cc b/chrome/browser/ui/app_list/arc/arc_app_utils.cc index e1f9071..b75f830d 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_utils.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_utils.cc
@@ -16,6 +16,7 @@ #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/session_manager_client.h" #include "components/arc/arc_bridge_service.h" +#include "components/arc/common/intent_helper.mojom.h" #include "ui/aura/window.h" #include "ui/display/display.h" #include "ui/display/screen.h"
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_mus.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_mus.cc index 2cad357..93064ebd 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_mus.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_mus.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_mus.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/ash/chrome_launcher_prefs.h" #include "chrome/browser/ui/ash/launcher/launcher_controller_helper.h" #include "extensions/grit/extensions_browser_resources.h" @@ -49,7 +50,9 @@ DISALLOW_COPY_AND_ASSIGN(ChromeShelfItemDelegate); }; -ChromeLauncherControllerMus::ChromeLauncherControllerMus() {} +ChromeLauncherControllerMus::ChromeLauncherControllerMus() { + AttachProfile(ProfileManager::GetActiveUserProfile()); +} ChromeLauncherControllerMus::~ChromeLauncherControllerMus() {}
diff --git a/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm b/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm index 6291a4c..00c7d35d 100644 --- a/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm +++ b/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm
@@ -444,22 +444,27 @@ } [containerView_ setHighlight:std::move(highlight)]; - std::vector<ToolbarActionViewController*> toolbar_actions = + std::vector<ToolbarActionViewController*> toolbarActions = toolbarActionsBar_->GetActions(); - for (NSUInteger i = 0; i < [buttons_ count]; ++i) { - ToolbarActionViewController* controller = - [[self buttonAtIndex:i] viewController]; - if (controller != toolbar_actions[i]) { - size_t j = i + 1; - while (true) { - ToolbarActionViewController* other_controller = - [[self buttonAtIndex:j] viewController]; - if (other_controller == toolbar_actions[i]) - break; - ++j; - } - [buttons_ exchangeObjectAtIndex:i withObjectAtIndex:j]; + // Check that every button has an action in the referenced actions. + // Tracking down crbug.com/653100. + // TODO(devlin): Remove or relax this one the bug is fixed? + for (BrowserActionButton* button in buttons_.get()) { + CHECK(std::find(toolbarActions.begin(), toolbarActions.end(), + [button viewController]) != toolbarActions.end()); + } + // Reorder |buttons_| to reflect |toolbarActions|. (Ugly n^2 sort, but the + // data set should be tiny.) + for (size_t refIndex = 0; refIndex < toolbarActions.size(); ++refIndex) { + NSUInteger buttonIndex = refIndex; + ToolbarActionViewController* refAction = toolbarActions[refIndex]; + for (; buttonIndex < [buttons_ count]; ++buttonIndex) { + if ([[self buttonAtIndex:buttonIndex] viewController] == refAction) + break; } + CHECK_LT(buttonIndex, [buttons_ count]); + if (buttonIndex != refIndex) + [buttons_ exchangeObjectAtIndex:buttonIndex withObjectAtIndex:refIndex]; } NSUInteger startIndex = toolbarActionsBar_->GetStartIndexInBounds();
diff --git a/chrome/browser/ui/cocoa/framed_browser_window_unittest.mm b/chrome/browser/ui/cocoa/framed_browser_window_unittest.mm index 5e88e91d..ff640dbe 100644 --- a/chrome/browser/ui/cocoa/framed_browser_window_unittest.mm +++ b/chrome/browser/ui/cocoa/framed_browser_window_unittest.mm
@@ -103,8 +103,7 @@ } // Test to make sure that our window widgets are in the right place. -// TODO(crbug.com/655112): Fails on Mac 10.11 Tests. -TEST_F(FramedBrowserWindowTest, DISABLED_WindowWidgetLocation) { +TEST_F(FramedBrowserWindowTest, WindowWidgetLocation) { BOOL yes = YES; BOOL no = NO; @@ -113,6 +112,8 @@ window_ = [[FramedBrowserWindow alloc] initWithContentRect:NSMakeRect(0, 0, 800, 600) hasTabStrip:NO]; + // Update window layout according to existing layout constraints. + [window_ layoutIfNeeded]; id controller = [OCMockObject mockForClass:[BrowserWindowController class]]; [[[controller stub] andReturnValue:OCMOCK_VALUE(yes)] isKindOfClass:[BrowserWindowController class]]; @@ -123,7 +124,8 @@ NSView* closeBoxControl = [window_ standardWindowButton:NSWindowCloseButton]; EXPECT_TRUE(closeBoxControl); - NSRect closeBoxFrame = [closeBoxControl frame]; + NSRect closeBoxFrame = [closeBoxControl convertRect:[closeBoxControl bounds] + toView:nil]; NSRect windowBounds = [window_ frame]; windowBounds = [[window_ contentView] convertRect:windowBounds fromView:nil]; windowBounds.origin = NSZeroPoint; @@ -136,7 +138,9 @@ NSView* miniaturizeControl = [window_ standardWindowButton:NSWindowMiniaturizeButton]; EXPECT_TRUE(miniaturizeControl); - NSRect miniaturizeFrame = [miniaturizeControl frame]; + NSRect miniaturizeFrame = + [miniaturizeControl convertRect:[miniaturizeControl bounds] + toView:nil]; EXPECT_EQ(NSMaxY(miniaturizeFrame), NSMaxY(windowBounds) - kFramedWindowButtonsWithoutTabStripOffsetFromTop); @@ -149,6 +153,8 @@ window_ = [[FramedBrowserWindow alloc] initWithContentRect:NSMakeRect(0, 0, 800, 600) hasTabStrip:YES]; + // Update window layout according to existing layout constraints. + [window_ layoutIfNeeded]; controller = [OCMockObject mockForClass:[BrowserWindowController class]]; [[[controller stub] andReturnValue:OCMOCK_VALUE(yes)] isKindOfClass:[BrowserWindowController class]]; @@ -159,7 +165,8 @@ closeBoxControl = [window_ standardWindowButton:NSWindowCloseButton]; EXPECT_TRUE(closeBoxControl); - closeBoxFrame = [closeBoxControl frame]; + closeBoxFrame = [closeBoxControl convertRect:[closeBoxControl bounds] + toView:nil]; windowBounds = [window_ frame]; windowBounds = [[window_ contentView] convertRect:windowBounds fromView:nil]; windowBounds.origin = NSZeroPoint; @@ -171,7 +178,8 @@ miniaturizeControl = [window_ standardWindowButton:NSWindowMiniaturizeButton]; EXPECT_TRUE(miniaturizeControl); - miniaturizeFrame = [miniaturizeControl frame]; + miniaturizeFrame = [miniaturizeControl convertRect:[miniaturizeControl bounds] + toView:nil]; EXPECT_EQ(NSMaxY(miniaturizeFrame), NSMaxY(windowBounds) - kFramedWindowButtonsWithTabStripOffsetFromTop);
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm index d380384..97eb5f5 100644 --- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm +++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
@@ -1180,14 +1180,17 @@ [self setNewTabButtonHoverState:shouldShowHover]; // Move the new tab button into place. We want to animate the new tab - // button if it's moving to the left (closing a tab), but not when it's - // moving to the right (inserting a new tab). If moving right, we need + // button if it's moving back (closing a tab), but not when it's + // moving forward (inserting a new tab). If moving forward, we need // to use a very small duration to make sure we cancel any in-flight // animation to the left. if (visible && animate) { ScopedNSAnimationContextGroup localAnimationGroup(true); - BOOL movingLeft = NSMinX(newTabNewFrame) < NSMinX(newTabTargetFrame_); - if (!movingLeft) { + BOOL movingBack = NSMinX(newTabNewFrame) < NSMinX(newTabTargetFrame_); + if (cocoa_l10n_util::ShouldDoExperimentalRTLLayout()) + movingBack = !movingBack; + + if (!movingBack) { localAnimationGroup.SetCurrentContextShortestDuration(); } [[newTabButton_ animator] setFrame:newTabNewFrame];
diff --git a/chrome/browser/ui/libgtk2ui/select_file_dialog_impl_gtk2.cc b/chrome/browser/ui/libgtk2ui/select_file_dialog_impl_gtk2.cc index 5ccff62..f26e0e90 100644 --- a/chrome/browser/ui/libgtk2ui/select_file_dialog_impl_gtk2.cc +++ b/chrome/browser/ui/libgtk2ui/select_file_dialog_impl_gtk2.cc
@@ -170,17 +170,20 @@ params_map_[dialog] = params; // Disable input events handling in the host window to make this dialog modal. - aura::WindowTreeHost* host = owning_window->GetHost(); - if (host) { - std::unique_ptr<base::Closure> callback = - views::DesktopWindowTreeHostX11::GetHostForXID( - host->GetAcceleratedWidget())->DisableEventListening( - GDK_WINDOW_XID(gtk_widget_get_window(dialog))); - // OnFilePickerDestroy() is called when |dialog| destroyed, which allows to - // invoke the callback function to re-enable events on the owning window. - g_object_set_data_full(G_OBJECT(dialog), "callback", callback.release(), - reinterpret_cast<GDestroyNotify>(OnFilePickerDestroy)); - gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); + if (owning_window) { + aura::WindowTreeHost* host = owning_window->GetHost(); + if (host) { + std::unique_ptr<base::Closure> callback = + views::DesktopWindowTreeHostX11::GetHostForXID( + host->GetAcceleratedWidget())->DisableEventListening( + GDK_WINDOW_XID(gtk_widget_get_window(dialog))); + // OnFilePickerDestroy() is called when |dialog| destroyed, which allows + // to invoke the callback function to re-enable event handling on the + // owning window. + g_object_set_data_full(G_OBJECT(dialog), "callback", callback.release(), + reinterpret_cast<GDestroyNotify>(OnFilePickerDestroy)); + gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); + } } gtk_widget_show_all(dialog);
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc index df3e65271..961e8ae 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc +++ b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
@@ -336,7 +336,7 @@ } void ToolbarActionsBar::CreateActions() { - DCHECK(toolbar_actions_.empty()); + CHECK(toolbar_actions_.empty()); // If the model isn't initialized, wait for it. if (!model_ || !model_->actions_initialized()) return; @@ -633,7 +633,8 @@ void ToolbarActionsBar::OnToolbarActionAdded( const ToolbarActionsModel::ToolbarItem& item, int index) { - DCHECK(GetActionForId(item.id) == nullptr) + CHECK(model_->actions_initialized()); + CHECK(GetActionForId(item.id) == nullptr) << "Asked to add a toolbar action view for an action that already " "exists"; @@ -641,10 +642,6 @@ model_->CreateActionForItem(browser_, this, item)); delegate_->AddViewForAction(toolbar_actions_[index], index); - // If we are still initializing the container, don't bother animating. - if (!model_->actions_initialized()) - return; - // We may need to resize (e.g. to show the new icon, or the chevron). We don't // need to check if an extension is upgrading here, because ResizeDelegate() // checks to see if the container is already the proper size, and because @@ -782,7 +779,7 @@ void ToolbarActionsBar::OnToolbarModelInitialized() { // We shouldn't have any actions before the model is initialized. - DCHECK(toolbar_actions_.empty()); + CHECK(toolbar_actions_.empty()); CreateActions(); // TODO(robliao): Remove ScopedTracker below once https://crbug.com/463337 is
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model.cc b/chrome/browser/ui/toolbar/toolbar_actions_model.cc index 1a3afa1..78fe600 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_model.cc +++ b/chrome/browser/ui/toolbar/toolbar_actions_model.cc
@@ -334,7 +334,7 @@ void ToolbarActionsModel::AddItem(const ToolbarItem& item) { // We only use AddItem() once the system is initialized. - DCHECK(actions_initialized_); + CHECK(actions_initialized_); // See if we have a last known good position for this extension. bool is_new_extension = !base::ContainsValue(last_known_positions_, item.id); @@ -460,7 +460,7 @@ // 2. Create a vector of actions that did not have a pref value. // 3. Remove holes from the sorted vector and append the unsorted vector. void ToolbarActionsModel::InitializeActionList() { - DCHECK(toolbar_items_.empty()); // We shouldn't have any items yet. + CHECK(toolbar_items_.empty()); // We shouldn't have any items yet. last_known_positions_ = extension_prefs_->GetToolbarOrder(); if (profile_->IsOffTheRecord())
diff --git a/chrome/browser/ui/views/download/download_shelf_context_menu_view.cc b/chrome/browser/ui/views/download/download_shelf_context_menu_view.cc index 0d5f4559..20ab817f 100644 --- a/chrome/browser/ui/views/download/download_shelf_context_menu_view.cc +++ b/chrome/browser/ui/views/download/download_shelf_context_menu_view.cc
@@ -10,7 +10,6 @@ #include "content/public/browser/download_item.h" #include "content/public/browser/page_navigator.h" #include "ui/gfx/geometry/point.h" -#include "ui/views/controls/menu/menu_model_adapter.h" #include "ui/views/controls/menu/menu_runner.h" DownloadShelfContextMenuView::DownloadShelfContextMenuView( @@ -29,14 +28,12 @@ // Run() should not be getting called if the DownloadItem was destroyed. DCHECK(menu_model); - menu_model_adapter_.reset(new views::MenuModelAdapter( - menu_model, base::Bind(&DownloadShelfContextMenuView::OnMenuClosed, - base::Unretained(this), on_menu_closed_callback))); - - menu_runner_.reset(new views::MenuRunner(menu_model_adapter_->CreateMenu(), - views::MenuRunner::HAS_MNEMONICS | - views::MenuRunner::CONTEXT_MENU | - views::MenuRunner::ASYNC)); + menu_runner_.reset(new views::MenuRunner( + menu_model, + views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU | + views::MenuRunner::ASYNC, + base::Bind(&DownloadShelfContextMenuView::OnMenuClosed, + base::Unretained(this), on_menu_closed_callback))); // The menu's alignment is determined based on the UI layout. views::MenuAnchorPosition position; @@ -52,11 +49,9 @@ const base::Closure& on_menu_closed_callback) { close_time_ = base::TimeTicks::Now(); - // This must be ran before clearing |menu_model_adapter_| who owns the - // reference. + // This must be run before clearing |menu_runner_| who owns the reference. if (!on_menu_closed_callback.is_null()) on_menu_closed_callback.Run(); - menu_model_adapter_.reset(); menu_runner_.reset(); }
diff --git a/chrome/browser/ui/views/download/download_shelf_context_menu_view.h b/chrome/browser/ui/views/download/download_shelf_context_menu_view.h index b956e6a..53cd991 100644 --- a/chrome/browser/ui/views/download/download_shelf_context_menu_view.h +++ b/chrome/browser/ui/views/download/download_shelf_context_menu_view.h
@@ -23,7 +23,6 @@ } namespace views { -class MenuModelAdapter; class MenuRunner; class Widget; } @@ -43,10 +42,9 @@ const base::Closure& on_menu_closed_callback); private: - // Callback for MenuModelAdapter + // Callback for MenuRunner. void OnMenuClosed(const base::Closure& on_menu_closed_callback); - std::unique_ptr<views::MenuModelAdapter> menu_model_adapter_; std::unique_ptr<views::MenuRunner> menu_runner_; // Time the menu was closed.
diff --git a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc index 2c04d3a..c8daa60c 100644 --- a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc +++ b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc
@@ -21,7 +21,6 @@ #include "ui/views/controls/button/image_button.h" #include "ui/views/controls/button/md_text_button.h" #include "ui/views/controls/label.h" -#include "ui/views/controls/menu/menu_model_adapter.h" #include "ui/views/controls/menu/menu_runner.h" #include "ui/views/controls/scroll_view.h" #include "ui/views/controls/separator.h" @@ -306,16 +305,13 @@ void MediaGalleriesDialogViews::ShowContextMenu(const gfx::Point& point, ui::MenuSourceType source_type, MediaGalleryPrefId id) { - menu_model_adapter_.reset(new views::MenuModelAdapter( + context_menu_runner_.reset(new views::MenuRunner( controller_->GetContextMenu(id), + views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU | + views::MenuRunner::ASYNC, base::Bind(&MediaGalleriesDialogViews::OnMenuClosed, base::Unretained(this)))); - context_menu_runner_.reset(new views::MenuRunner( - menu_model_adapter_->CreateMenu(), views::MenuRunner::HAS_MNEMONICS | - views::MenuRunner::CONTEXT_MENU | - views::MenuRunner::ASYNC)); - context_menu_runner_->RunMenuAt(GetWidget(), NULL, gfx::Rect(point.x(), point.y(), 0, 0), views::MENU_ANCHOR_TOPLEFT, source_type); @@ -326,7 +322,6 @@ } void MediaGalleriesDialogViews::OnMenuClosed() { - menu_model_adapter_.reset(); context_menu_runner_.reset(); }
diff --git a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.h b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.h index 2971414..5ca9e9b 100644 --- a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.h +++ b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.h
@@ -18,7 +18,6 @@ namespace views { class Checkbox; class LabelButton; -class MenuModelAdapter; class MenuRunner; class Widget; } @@ -88,7 +87,7 @@ // In unit tests, it may not. bool ControllerHasWebContents() const; - // Callback for MenuModelAdapter. + // Callback for MenuRunner. void OnMenuClosed(); MediaGalleriesDialogController* controller_; @@ -111,7 +110,6 @@ // True if the user has pressed accept. bool accepted_; - std::unique_ptr<views::MenuModelAdapter> menu_model_adapter_; std::unique_ptr<views::MenuRunner> context_menu_runner_; DISALLOW_COPY_AND_ASSIGN(MediaGalleriesDialogViews);
diff --git a/chrome/browser/ui/views/frame/browser_frame.cc b/chrome/browser/ui/views/frame/browser_frame.cc index 2cbb185..ccacf482 100644 --- a/chrome/browser/ui/views/frame/browser_frame.cc +++ b/chrome/browser/ui/views/frame/browser_frame.cc
@@ -28,7 +28,6 @@ #include "ui/base/hit_test.h" #include "ui/events/event_handler.h" #include "ui/gfx/font_list.h" -#include "ui/views/controls/menu/menu_model_adapter.h" #include "ui/views/controls/menu/menu_runner.h" #include "ui/views/widget/native_widget.h" @@ -260,13 +259,11 @@ views::View::ConvertPointFromScreen(non_client_view(), &point_in_view_coords); int hit_test = non_client_view()->NonClientHitTest(point_in_view_coords); if (hit_test == HTCAPTION || hit_test == HTNOWHERE) { - menu_model_adapter_.reset(new views::MenuModelAdapter( - GetSystemMenuModel(), - base::Bind(&BrowserFrame::OnMenuClosed, base::Unretained(this)))); menu_runner_.reset(new views::MenuRunner( - menu_model_adapter_->CreateMenu(), views::MenuRunner::HAS_MNEMONICS | - views::MenuRunner::CONTEXT_MENU | - views::MenuRunner::ASYNC)); + GetSystemMenuModel(), + views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU | + views::MenuRunner::ASYNC, + base::Bind(&BrowserFrame::OnMenuClosed, base::Unretained(this)))); menu_runner_->RunMenuAt(source->GetWidget(), nullptr, gfx::Rect(p, gfx::Size(0, 0)), views::MENU_ANCHOR_TOPLEFT, source_type); @@ -298,6 +295,5 @@ } void BrowserFrame::OnMenuClosed() { - menu_model_adapter_.reset(); menu_runner_.reset(); }
diff --git a/chrome/browser/ui/views/frame/browser_frame.h b/chrome/browser/ui/views/frame/browser_frame.h index 643043b..870a719d 100644 --- a/chrome/browser/ui/views/frame/browser_frame.h +++ b/chrome/browser/ui/views/frame/browser_frame.h
@@ -31,7 +31,6 @@ } namespace views { -class MenuModelAdapter; class MenuRunner; class View; } @@ -143,7 +142,6 @@ // Used to show the system menu. Only used if // NativeBrowserFrame::UsesNativeSystemMenu() returns false. - std::unique_ptr<views::MenuModelAdapter> menu_model_adapter_; std::unique_ptr<views::MenuRunner> menu_runner_; std::unique_ptr<ui::EventHandler> browser_command_handler_;
diff --git a/chrome/browser/ui/views/website_settings/website_settings_popup_view_unittest.cc b/chrome/browser/ui/views/website_settings/website_settings_popup_view_unittest.cc index 751f72ce..3f00e80 100644 --- a/chrome/browser/ui/views/website_settings/website_settings_popup_view_unittest.cc +++ b/chrome/browser/ui/views/website_settings/website_settings_popup_view_unittest.cc
@@ -15,7 +15,7 @@ #include "content/public/browser/ssl_status.h" #include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/test_web_contents_factory.h" -#include "device/core/mock_device_client.h" +#include "device/base/mock_device_client.h" #include "device/usb/mock_usb_device.h" #include "device/usb/mock_usb_service.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ui/website_settings/website_settings.cc b/chrome/browser/ui/website_settings/website_settings.cc index ac64aec..48af6a2 100644 --- a/chrome/browser/ui/website_settings/website_settings.cc +++ b/chrome/browser/ui/website_settings/website_settings.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/website_settings/website_settings.h" +#include <openssl/ssl.h> #include <stddef.h> #include <stdint.h> @@ -647,12 +648,21 @@ (security_info.connection_status & net::SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION) != 0; const char *key_exchange, *cipher, *mac; - bool is_aead; - net::SSLCipherSuiteToStrings( - &key_exchange, &cipher, &mac, &is_aead, cipher_suite); + bool is_aead, is_tls13; + net::SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, + &is_tls13, cipher_suite); site_connection_details_ += ASCIIToUTF16("\n\n"); if (is_aead) { + if (is_tls13) { + // For TLS 1.3 ciphers, report the group (historically, curve) as the + // key exchange. + key_exchange = SSL_get_curve_name(security_info.key_exchange_group); + if (!key_exchange) { + NOTREACHED(); + key_exchange = ""; + } + } site_connection_details_ += l10n_util::GetStringFUTF16( IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTION_DETAILS_AEAD, ASCIIToUTF16(cipher), ASCIIToUTF16(key_exchange));
diff --git a/chrome/browser/ui/website_settings/website_settings_unittest.cc b/chrome/browser/ui/website_settings/website_settings_unittest.cc index d1079ed..89db415 100644 --- a/chrome/browser/ui/website_settings/website_settings_unittest.cc +++ b/chrome/browser/ui/website_settings/website_settings_unittest.cc
@@ -26,7 +26,7 @@ #include "components/content_settings/core/common/content_settings_types.h" #include "components/infobars/core/infobar.h" #include "content/public/browser/ssl_status.h" -#include "device/core/mock_device_client.h" +#include "device/base/mock_device_client.h" #include "device/usb/mock_usb_device.h" #include "device/usb/mock_usb_service.h" #include "net/cert/cert_status_flags.h"
diff --git a/chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals_ui.cc b/chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals_ui.cc index 74ac166..b2cea0e 100644 --- a/chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals_ui.cc +++ b/chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals_ui.cc
@@ -22,7 +22,10 @@ IDR_BLUETOOTH_INTERNALS_JS); html_source->AddResourcePath( "device/bluetooth/public/interfaces/adapter.mojom", - IDR_BLUETOOTH_MOJO_JS); + IDR_BLUETOOTH_ADAPTER_MOJO_JS); + html_source->AddResourcePath( + "device/bluetooth/public/interfaces/device.mojom", + IDR_BLUETOOTH_DEVICE_MOJO_JS); html_source->SetDefaultResource(IDR_BLUETOOTH_INTERNALS_HTML); html_source->DisableI18nAndUseGzipForAllPaths();
diff --git a/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc b/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc index 23ec4ec..276cca0d 100644 --- a/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc +++ b/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
@@ -70,7 +70,7 @@ DCHECK(gcache_summary); // Use this map to sort the result list by the path. - std::map<base::FilePath, base::DictionaryValue*> files; + std::map<base::FilePath, std::unique_ptr<base::DictionaryValue>> files; const int options = (base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES | @@ -86,7 +86,7 @@ const bool is_symbolic_link = base::IsLink(info.GetName()); const base::Time last_modified = info.GetLastModifiedTime(); - base::DictionaryValue* entry = new base::DictionaryValue; + auto entry = base::MakeUnique<base::DictionaryValue>(); entry->SetString("path", current.value()); // Use double instead of integer for large files. entry->SetDouble("size", size); @@ -99,16 +99,14 @@ entry->SetString( "permission", base::StringPrintf("%03o", info.stat().st_mode & 0x1ff)); - files[current] = entry; + files[current] = std::move(entry); total_size += size; } // Convert |files| into |gcache_contents|. - for (std::map<base::FilePath, base::DictionaryValue*>::const_iterator - iter = files.begin(); iter != files.end(); ++iter) { - gcache_contents->Append(iter->second); - } + for (auto& it : files) + gcache_contents->Append(std::move(it.second)); gcache_summary->SetDouble("total_size", total_size); }
diff --git a/chrome/browser/ui/webui/chromeos/login/l10n_util.cc b/chrome/browser/ui/webui/chromeos/login/l10n_util.cc index e6fe8c9..0130de1 100644 --- a/chrome/browser/ui/webui/chromeos/login/l10n_util.cc +++ b/chrome/browser/ui/webui/chromeos/login/l10n_util.cc
@@ -76,7 +76,7 @@ input_methods_list->Append(std::move(optgroup)); } -base::DictionaryValue* CreateLanguageEntry( +std::unique_ptr<base::DictionaryValue> CreateLanguageEntry( const std::string& language_code, const base::string16& language_display_name, const base::string16& language_native_display_name) { @@ -89,13 +89,12 @@ base::i18n::StringContainsStrongRTLChars(display_name); const std::string directionality = has_rtl_chars ? "rtl" : "ltr"; - std::unique_ptr<base::DictionaryValue> dictionary( - new base::DictionaryValue()); + auto dictionary = base::MakeUnique<base::DictionaryValue>(); dictionary->SetString("code", language_code); dictionary->SetString("displayName", language_display_name); dictionary->SetString("textDirection", directionality); dictionary->SetString("nativeDisplayName", language_native_display_name); - return dictionary.release(); + return dictionary; } // Gets the list of languages with |descriptors| based on |base_language_codes|.
diff --git a/chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.cc index 98ee60c..af896ab 100644 --- a/chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.cc
@@ -6,6 +6,7 @@ #include <utility> +#include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" @@ -232,13 +233,13 @@ it != users.end(); ++it) { bool is_owner = ((*it)->email() == owner); - base::DictionaryValue* user_dict = new base::DictionaryValue(); + auto user_dict = base::MakeUnique<base::DictionaryValue>(); UserSelectionScreen::FillUserDictionary( *it, is_owner, false, /* is_signin_to_add */ proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, NULL, /* public_session_recommended_locales */ - user_dict); - users_list->Append(user_dict); + user_dict.get()); + users_list->Append(std::move(user_dict)); } data->Set("managers", users_list.release()); ShowScreenWithData(OobeScreen::SCREEN_CREATE_SUPERVISED_USER_FLOW,
diff --git a/chrome/browser/ui/webui/chromeos/network_ui.cc b/chrome/browser/ui/webui/chromeos/network_ui.cc index 8c105fd..8dfc7c2b4 100644 --- a/chrome/browser/ui/webui/chromeos/network_ui.cc +++ b/chrome/browser/ui/webui/chromeos/network_ui.cc
@@ -60,7 +60,7 @@ std::unique_ptr<base::ListValue> ip_configs(new base::ListValue); for (base::DictionaryValue::Iterator iter(device_state->ip_configs()); !iter.IsAtEnd(); iter.Advance()) { - ip_configs->Append(iter.value().DeepCopy()); + ip_configs->Append(iter.value().CreateDeepCopy()); } device_dictionary->SetWithoutPathExpansion(shill::kIPConfigsProperty, ip_configs.release());
diff --git a/chrome/browser/ui/webui/cookies_tree_model_util.cc b/chrome/browser/ui/webui/cookies_tree_model_util.cc index 82611ad..9e23782 100644 --- a/chrome/browser/ui/webui/cookies_tree_model_util.cc +++ b/chrome/browser/ui/webui/cookies_tree_model_util.cc
@@ -299,6 +299,19 @@ dict->SetString(kKeyDomain, node.GetDetailedInfo().flash_lso_domain); break; } + case CookieTreeNode::DetailedInfo::TYPE_MEDIA_LICENSE: { + dict->SetString(kKeyType, "media_license"); + dict->SetString(kKeyIcon, "chrome://theme/IDR_COOKIE_STORAGE_ICON"); + + const BrowsingDataMediaLicenseHelper::MediaLicenseInfo& + media_license_info = *node.GetDetailedInfo().media_license_info; + dict->SetString(kKeyOrigin, media_license_info.origin.spec()); + dict->SetString(kKeySize, ui::FormatBytes(media_license_info.size)); + dict->SetString(kKeyModified, + base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime( + media_license_info.last_modified_time))); + break; + } default: #if defined(OS_MACOSX) dict->SetString(kKeyIcon, "chrome://theme/IDR_BOOKMARK_BAR_FOLDER");
diff --git a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc index 674d384..dd641b5 100644 --- a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc +++ b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
@@ -65,8 +65,8 @@ // not used in displaying any real interstitials. class InterstitialHTMLSource : public content::URLDataSource { public: - explicit InterstitialHTMLSource(content::WebContents* web_contents); - ~InterstitialHTMLSource() override; + InterstitialHTMLSource() {} + ~InterstitialHTMLSource() override {} // content::URLDataSource: std::string GetMimeType(const std::string& mime_type) const override; @@ -80,7 +80,6 @@ const content::URLDataSource::GotDataCallback& callback) override; private: - content::WebContents* web_contents_; DISALLOW_COPY_AND_ASSIGN(InterstitialHTMLSource); }; @@ -308,10 +307,8 @@ InterstitialUI::InterstitialUI(content::WebUI* web_ui) : WebUIController(web_ui) { - std::unique_ptr<InterstitialHTMLSource> html_source( - new InterstitialHTMLSource(web_ui->GetWebContents())); Profile* profile = Profile::FromWebUI(web_ui); - content::URLDataSource::Add(profile, html_source.release()); + content::URLDataSource::Add(profile, new InterstitialHTMLSource()); } InterstitialUI::~InterstitialUI() { @@ -319,14 +316,6 @@ // InterstitialHTMLSource -InterstitialHTMLSource::InterstitialHTMLSource( - content::WebContents* web_contents) - : web_contents_(web_contents) { -} - -InterstitialHTMLSource::~InterstitialHTMLSource() { -} - std::string InterstitialHTMLSource::GetMimeType( const std::string& mime_type) const { return "text/html"; @@ -353,20 +342,21 @@ const std::string& path, const content::ResourceRequestInfo::WebContentsGetter& wc_getter, const content::URLDataSource::GotDataCallback& callback) { + content::WebContents* web_contents = wc_getter.Run(); std::unique_ptr<content::InterstitialPageDelegate> interstitial_delegate; if (base::StartsWith(path, "ssl", base::CompareCase::SENSITIVE)) { - interstitial_delegate.reset(CreateSSLBlockingPage(web_contents_)); + interstitial_delegate.reset(CreateSSLBlockingPage(web_contents)); } else if (base::StartsWith(path, "safebrowsing", base::CompareCase::SENSITIVE)) { - interstitial_delegate.reset(CreateSafeBrowsingBlockingPage(web_contents_)); + interstitial_delegate.reset(CreateSafeBrowsingBlockingPage(web_contents)); } else if (base::StartsWith(path, "clock", base::CompareCase::SENSITIVE)) { - interstitial_delegate.reset(CreateBadClockBlockingPage(web_contents_)); + interstitial_delegate.reset(CreateBadClockBlockingPage(web_contents)); } #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) else if (base::StartsWith(path, "captiveportal", base::CompareCase::SENSITIVE)) { - interstitial_delegate.reset(CreateCaptivePortalBlockingPage(web_contents_)); + interstitial_delegate.reset(CreateCaptivePortalBlockingPage(web_contents)); } #endif std::string html;
diff --git a/chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.cc index 8cb4150..f01dcc4 100644 --- a/chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.cc +++ b/chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.cc
@@ -13,6 +13,7 @@ #include "base/bind.h" #include "base/location.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" @@ -69,10 +70,11 @@ // Creates a user info dictionary to be stored in the |ListValue| that is // passed to Javascript for the |kAccountsPrefUsers| preference. -base::DictionaryValue* CreateUserInfo(const std::string& username, - const std::string& display_email, - const std::string& display_name) { - base::DictionaryValue* user_dict = new base::DictionaryValue; +std::unique_ptr<base::DictionaryValue> CreateUserInfo( + const std::string& username, + const std::string& display_email, + const std::string& display_name) { + auto user_dict = base::MakeUnique<base::DictionaryValue>(); user_dict->SetString("username", username); user_dict->SetString("name", display_email); user_dict->SetString("email", display_name);
diff --git a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc index d9daf77c..68c5fa3 100644 --- a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc +++ b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
@@ -158,12 +158,12 @@ return mode; } -base::DictionaryValue* ConvertDisplayModeToValue( +std::unique_ptr<base::DictionaryValue> ConvertDisplayModeToValue( int64_t display_id, const scoped_refptr<display::ManagedDisplayMode>& mode) { bool is_internal = display::Display::HasInternalDisplay() && display::Display::InternalDisplayId() == display_id; - base::DictionaryValue* result = new base::DictionaryValue(); + auto result = base::MakeUnique<base::DictionaryValue>(); gfx::Size size_dip = mode->GetSizeInDIP(is_internal); result->SetInteger("width", size_dip.width()); result->SetInteger("height", size_dip.height());
diff --git a/chrome/browser/ui/webui/options/cookies_view_handler.cc b/chrome/browser/ui/webui/options/cookies_view_handler.cc index deac6640..fed3637 100644 --- a/chrome/browser/ui/webui/options/cookies_view_handler.cc +++ b/chrome/browser/ui/webui/options/cookies_view_handler.cc
@@ -21,6 +21,7 @@ #include "chrome/browser/browsing_data/browsing_data_flash_lso_helper.h" #include "chrome/browser/browsing_data/browsing_data_indexed_db_helper.h" #include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h" +#include "chrome/browser/browsing_data/browsing_data_media_license_helper.h" #include "chrome/browser/browsing_data/browsing_data_quota_helper.h" #include "chrome/browser/browsing_data/browsing_data_service_worker_helper.h" #include "chrome/browser/profiles/profile.h" @@ -110,6 +111,12 @@ {"label_channel_id_expires", IDS_COOKIES_CHANNEL_ID_EXPIRES_LABEL}, {"label_protected_by_apps", IDS_GEOLOCATION_SET_BY_HOVER}, // TODO(bauerb): Use a better string + {"cookie_media_license", IDS_COOKIES_MEDIA_LICENSE}, + {"label_media_license_origin", IDS_COOKIES_LOCAL_STORAGE_ORIGIN_LABEL}, + {"label_media_license_size", + IDS_COOKIES_LOCAL_STORAGE_SIZE_ON_DISK_LABEL}, + {"label_media_license_last_modified", + IDS_COOKIES_LOCAL_STORAGE_LAST_MODIFIED_LABEL}, }; RegisterStrings(localized_strings, resources, arraysize(resources)); @@ -216,7 +223,8 @@ BrowsingDataChannelIDHelper::Create(profile->GetRequestContext()), new BrowsingDataServiceWorkerHelper(service_worker_context), new BrowsingDataCacheStorageHelper(cache_storage_context), - BrowsingDataFlashLSOHelper::Create(profile)); + BrowsingDataFlashLSOHelper::Create(profile), + BrowsingDataMediaLicenseHelper::Create(file_system_context)); cookies_tree_model_.reset(new CookiesTreeModel( container, profile->GetExtensionSpecialStoragePolicy())); cookies_tree_model_->AddCookiesTreeObserver(this);
diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc b/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc index 4116618e..0894f36 100644 --- a/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc +++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc
@@ -20,7 +20,7 @@ #include "chrome/browser/printing/pwg_raster_converter.h" #include "components/cloud_devices/common/cloud_device_description.h" #include "components/cloud_devices/common/printer_description.h" -#include "device/core/device_client.h" +#include "device/base/device_client.h" #include "device/usb/usb_device.h" #include "device/usb/usb_service.h" #include "extensions/browser/api/device_permissions_manager.h"
diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc b/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc index 28cf5af..608ab31c 100644 --- a/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc +++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc
@@ -28,7 +28,7 @@ #include "chrome/browser/printing/pwg_raster_converter.h" #include "chrome/test/base/testing_profile.h" #include "components/version_info/version_info.h" -#include "device/core/mock_device_client.h" +#include "device/base/mock_device_client.h" #include "device/usb/mock_usb_device.h" #include "device/usb/mock_usb_service.h" #include "extensions/browser/api/device_permissions_manager.h"
diff --git a/chrome/browser/ui/webui/settings/appearance_handler.cc b/chrome/browser/ui/webui/settings/appearance_handler.cc index 79ae0fd..eac391fb5 100644 --- a/chrome/browser/ui/webui/settings/appearance_handler.cc +++ b/chrome/browser/ui/webui/settings/appearance_handler.cc
@@ -7,11 +7,9 @@ #include "base/bind.h" #include "base/logging.h" #include "base/values.h" -#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/themes/theme_service.h" #include "chrome/browser/themes/theme_service_factory.h" -#include "content/public/browser/notification_source.h" #include "content/public/browser/web_ui.h" #if defined(OS_CHROMEOS) @@ -27,14 +25,20 @@ AppearanceHandler::~AppearanceHandler() {} +void AppearanceHandler::OnJavascriptAllowed() {} +void AppearanceHandler::OnJavascriptDisallowed() {} + void AppearanceHandler::RegisterMessages() { web_ui()->RegisterMessageCallback( - "resetTheme", - base::Bind(&AppearanceHandler::HandleResetTheme, base::Unretained(this))); - web_ui()->RegisterMessageCallback( - "getResetThemeEnabled", - base::Bind(&AppearanceHandler::HandleGetResetThemeEnabled, + "useDefaultTheme", + base::Bind(&AppearanceHandler::HandleUseDefaultTheme, base::Unretained(this))); +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) + web_ui()->RegisterMessageCallback( + "useSystemTheme", + base::Bind(&AppearanceHandler::HandleUseSystemTheme, + base::Unretained(this))); +#endif #if defined(OS_CHROMEOS) web_ui()->RegisterMessageCallback( "openWallpaperManager", @@ -43,46 +47,15 @@ #endif } -void AppearanceHandler::OnJavascriptAllowed() { - registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED, - content::Source<ThemeService>( - ThemeServiceFactory::GetForProfile(profile_))); -} - -void AppearanceHandler::OnJavascriptDisallowed() { - registrar_.RemoveAll(); -} - -void AppearanceHandler::Observe( - int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - DCHECK_EQ(chrome::NOTIFICATION_BROWSER_THEME_CHANGED, type); - - CallJavascriptFunction("cr.webUIListenerCallback", - base::StringValue("reset-theme-enabled-changed"), - base::FundamentalValue(ResetThemeEnabled())); -} - -void AppearanceHandler::HandleResetTheme(const base::ListValue* /*args*/) { +void AppearanceHandler::HandleUseDefaultTheme(const base::ListValue* args) { ThemeServiceFactory::GetForProfile(profile_)->UseDefaultTheme(); } -bool AppearanceHandler::ResetThemeEnabled() const { - // TODO(jhawkins): Handle native/system theme button. - return !ThemeServiceFactory::GetForProfile(profile_)->UsingDefaultTheme(); +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) +void AppearanceHandler::HandleUseSystemTheme(const base::ListValue* args) { + ThemeServiceFactory::GetForProfile(profile_)->UseSystemTheme(); } - -void AppearanceHandler::HandleGetResetThemeEnabled( - const base::ListValue* args) { - AllowJavascript(); - - CHECK_EQ(1U, args->GetSize()); - const base::Value* callback_id; - CHECK(args->Get(0, &callback_id)); - ResolveJavascriptCallback(*callback_id, - base::FundamentalValue(ResetThemeEnabled())); -} +#endif #if defined(OS_CHROMEOS) void AppearanceHandler::HandleOpenWallpaperManager(
diff --git a/chrome/browser/ui/webui/settings/appearance_handler.h b/chrome/browser/ui/webui/settings/appearance_handler.h index 8452d5d..a00a9637 100644 --- a/chrome/browser/ui/webui/settings/appearance_handler.h +++ b/chrome/browser/ui/webui/settings/appearance_handler.h
@@ -7,8 +7,6 @@ #include "base/macros.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" namespace base { class ListValue; @@ -23,8 +21,7 @@ namespace settings { // Chrome "Appearance" settings page UI handler. -class AppearanceHandler : public SettingsPageUIHandler, - public content::NotificationObserver { +class AppearanceHandler : public SettingsPageUIHandler { public: explicit AppearanceHandler(content::WebUI* webui); ~AppearanceHandler() override; @@ -35,19 +32,13 @@ void OnJavascriptDisallowed() override; private: - // content::NotificationObserver implementation. - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; + // Changes the UI theme of the browser to the default theme. + void HandleUseDefaultTheme(const base::ListValue* args); - // Whether the theme can be reset. - bool ResetThemeEnabled() const; - - // Resets the UI theme of the browser to the default theme. - void HandleResetTheme(const base::ListValue* args); - - // Sends the enabled state of the reset-theme control to the JS. - void HandleGetResetThemeEnabled(const base::ListValue* args); +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) + // Changes the UI theme of the browser to the system (GTK+) theme. + void HandleUseSystemTheme(const base::ListValue* args); +#endif #if defined(OS_CHROMEOS) // Open the wallpaper manager app. @@ -56,9 +47,6 @@ Profile* profile_; // Weak pointer. - // Used to register for relevant notifications. - content::NotificationRegistrar registrar_; - DISALLOW_COPY_AND_ASSIGN(AppearanceHandler); };
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index 401a19a..26a2f22 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -256,8 +256,15 @@ LocalizedString localized_strings[] = { {"appearancePageTitle", IDS_SETTINGS_APPEARANCE}, {"exampleDotCom", IDS_SETTINGS_EXAMPLE_DOT_COM}, - {"theme", IDS_SETTINGS_THEME}, + {"themes", IDS_SETTINGS_THEMES}, +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) + {"systemTheme", IDS_SETTINGS_SYSTEM_THEME}, + {"useSystemTheme", IDS_SETTINGS_USE_SYSTEM_THEME}, + {"classicTheme", IDS_SETTINGS_CLASSIC_THEME}, + {"useClassicTheme", IDS_SETTINGS_USE_CLASSIC_THEME}, +#else {"resetToDefaultTheme", IDS_SETTINGS_RESET_TO_DEFAULT_THEME}, +#endif {"showHomeButton", IDS_SETTINGS_SHOW_HOME_BUTTON}, {"showBookmarksBar", IDS_SETTINGS_SHOW_BOOKMARKS_BAR}, {"homePageNtp", IDS_SETTINGS_HOME_PAGE_NTP}, @@ -1307,6 +1314,7 @@ {"cookieFileSystem", IDS_COOKIES_FILE_SYSTEM}, {"cookieFlashLso", IDS_COOKIES_FLASH_LSO}, {"cookieLocalStorage", IDS_COOKIES_LOCAL_STORAGE}, + {"cookieMediaLicense", IDS_COOKIES_MEDIA_LICENSE}, {"cookiePlural", IDS_COOKIES_PLURAL_COOKIES}, {"cookieServiceWorker", IDS_COOKIES_SERVICE_WORKER}, {"cookieSingular", IDS_COOKIES_SINGLE_COOKIE}, @@ -1342,6 +1350,10 @@ IDS_COOKIES_LOCAL_STORAGE_LAST_MODIFIED_LABEL}, {"localStorageOrigin", IDS_COOKIES_LOCAL_STORAGE_ORIGIN_LABEL}, {"localStorageSize", IDS_COOKIES_LOCAL_STORAGE_SIZE_ON_DISK_LABEL}, + {"mediaLicenseOrigin", IDS_COOKIES_LOCAL_STORAGE_ORIGIN_LABEL}, + {"mediaLicenseSize", IDS_COOKIES_LOCAL_STORAGE_SIZE_ON_DISK_LABEL}, + {"mediaLicenseLastModified", + IDS_COOKIES_LOCAL_STORAGE_LAST_MODIFIED_LABEL}, {"serviceWorkerOrigin", IDS_COOKIES_LOCAL_STORAGE_ORIGIN_LABEL}, {"serviceWorkerScopes", IDS_COOKIES_SERVICE_WORKER_SCOPES_LABEL}, {"serviceWorkerSize", IDS_COOKIES_LOCAL_STORAGE_SIZE_ON_DISK_LABEL},
diff --git a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc index 076e09d..841fc877 100644 --- a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc +++ b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc
@@ -21,6 +21,7 @@ #include "chrome/browser/browsing_data/browsing_data_flash_lso_helper.h" #include "chrome/browser/browsing_data/browsing_data_indexed_db_helper.h" #include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h" +#include "chrome/browser/browsing_data/browsing_data_media_license_helper.h" #include "chrome/browser/browsing_data/browsing_data_quota_helper.h" #include "chrome/browser/browsing_data/browsing_data_service_worker_helper.h" #include "chrome/browser/profiles/profile.h" @@ -166,7 +167,8 @@ BrowsingDataChannelIDHelper::Create(profile->GetRequestContext()), new BrowsingDataServiceWorkerHelper(service_worker_context), new BrowsingDataCacheStorageHelper(cache_storage_context), - BrowsingDataFlashLSOHelper::Create(profile)); + BrowsingDataFlashLSOHelper::Create(profile), + BrowsingDataMediaLicenseHelper::Create(file_system_context)); cookies_tree_model_.reset( new CookiesTreeModel(container, profile->GetExtensionSpecialStoragePolicy()));
diff --git a/chrome/browser/ui/webui/usb_internals/usb_internals_page_handler.cc b/chrome/browser/ui/webui/usb_internals/usb_internals_page_handler.cc index 5f9117e..e6cdab4e 100644 --- a/chrome/browser/ui/webui/usb_internals/usb_internals_page_handler.cc +++ b/chrome/browser/ui/webui/usb_internals/usb_internals_page_handler.cc
@@ -7,7 +7,7 @@ #include "base/macros.h" #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" -#include "device/core/device_client.h" +#include "device/base/device_client.h" #include "device/usb/usb_device.h" #include "device/usb/usb_device_handle.h" #include "device/usb/usb_service.h"
diff --git a/chrome/browser/ui/webui/webui_webview_browsertest.cc b/chrome/browser/ui/webui/webui_webview_browsertest.cc index 07606928..3dc8459d 100644 --- a/chrome/browser/ui/webui/webui_webview_browsertest.cc +++ b/chrome/browser/ui/webui/webui_webview_browsertest.cc
@@ -23,6 +23,11 @@ #include "extensions/test/extension_test_message_listener.h" #include "net/test/embedded_test_server/embedded_test_server.h" +// Turn these tests off on Mac while we collect data on windows server crashes +// on mac chromium builders. +// http://crbug.com/653353 +#if !defined(OS_MACOSX) + #if !defined(OS_CHROMEOS) && defined(USE_AURA) #include "ui/aura/window.h" @@ -350,3 +355,5 @@ } } #endif + +#endif // !defined(OS_MACOSX)
diff --git a/chrome/browser/usb/DEPS b/chrome/browser/usb/DEPS index a41ab27..6d9fc40f 100644 --- a/chrome/browser/usb/DEPS +++ b/chrome/browser/usb/DEPS
@@ -1,6 +1,6 @@ include_rules = [ "+chrome/browser/ui", "+components/bubble", - "+device/core", + "+device/base", "+device/usb", ]
diff --git a/chrome/browser/usb/usb_chooser_context.cc b/chrome/browser/usb/usb_chooser_context.cc index c3d5965..231853d 100644 --- a/chrome/browser/usb/usb_chooser_context.cc +++ b/chrome/browser/usb/usb_chooser_context.cc
@@ -13,7 +13,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/profiles/profile.h" -#include "device/core/device_client.h" +#include "device/base/device_client.h" #include "device/usb/public/interfaces/device.mojom.h" #include "device/usb/usb_device.h"
diff --git a/chrome/browser/usb/usb_chooser_context_unittest.cc b/chrome/browser/usb/usb_chooser_context_unittest.cc index 1dc9eed..4159a8c 100644 --- a/chrome/browser/usb/usb_chooser_context_unittest.cc +++ b/chrome/browser/usb/usb_chooser_context_unittest.cc
@@ -8,7 +8,7 @@ #include "chrome/browser/usb/usb_chooser_context_factory.h" #include "chrome/test/base/testing_profile.h" #include "content/public/test/test_browser_thread_bundle.h" -#include "device/core/mock_device_client.h" +#include "device/base/mock_device_client.h" #include "device/usb/mock_usb_device.h" #include "device/usb/mock_usb_service.h"
diff --git a/chrome/browser/usb/usb_chooser_controller.cc b/chrome/browser/usb/usb_chooser_controller.cc index 59a6e16..2075f5917 100644 --- a/chrome/browser/usb/usb_chooser_controller.cc +++ b/chrome/browser/usb/usb_chooser_controller.cc
@@ -23,7 +23,7 @@ #include "chrome/grit/generated_resources.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" -#include "device/core/device_client.h" +#include "device/base/device_client.h" #include "device/usb/mojo/type_converters.h" #include "device/usb/usb_device.h" #include "device/usb/usb_device_filter.h"
diff --git a/chrome/browser/usb/usb_chooser_controller_unittest.cc b/chrome/browser/usb/usb_chooser_controller_unittest.cc index 4f32382..bcf2c3c 100644 --- a/chrome/browser/usb/usb_chooser_controller_unittest.cc +++ b/chrome/browser/usb/usb_chooser_controller_unittest.cc
@@ -10,7 +10,7 @@ #include "chrome/browser/usb/usb_chooser_controller.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "content/public/test/web_contents_tester.h" -#include "device/core/mock_device_client.h" +#include "device/base/mock_device_client.h" #include "device/usb/mock_usb_device.h" #include "device/usb/mock_usb_service.h" #include "device/usb/public/interfaces/device_manager.mojom.h"
diff --git a/chrome/browser/usb/web_usb_detector.cc b/chrome/browser/usb/web_usb_detector.cc index 3b20908..bc597c84 100644 --- a/chrome/browser/usb/web_usb_detector.cc +++ b/chrome/browser/usb/web_usb_detector.cc
@@ -16,7 +16,7 @@ #include "chrome/grit/generated_resources.h" #include "chrome/grit/theme_resources.h" #include "content/public/common/origin_util.h" -#include "device/core/device_client.h" +#include "device/base/device_client.h" #include "device/usb/usb_device.h" #include "device/usb/usb_ids.h" #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/usb/web_usb_detector_unittest.cc b/chrome/browser/usb/web_usb_detector_unittest.cc index f64661e..70b5f4c 100644 --- a/chrome/browser/usb/web_usb_detector_unittest.cc +++ b/chrome/browser/usb/web_usb_detector_unittest.cc
@@ -8,7 +8,7 @@ #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/usb/web_usb_detector.h" -#include "device/core/mock_device_client.h" +#include "device/base/mock_device_client.h" #include "device/usb/mock_usb_device.h" #include "device/usb/mock_usb_service.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/chrome_repack_locales.gni b/chrome/chrome_repack_locales.gni index b970f30..cb168e7 100644 --- a/chrome/chrome_repack_locales.gni +++ b/chrome/chrome_repack_locales.gni
@@ -71,11 +71,8 @@ ] } if (enable_extensions) { - source_patterns += [ - # TODO(jamescook): When Android stops building extensions code move - # this to the OS != 'ios' and OS != 'android' section. - "${root_gen_dir}/extensions/strings/extensions_strings_", - ] + source_patterns += + [ "${root_gen_dir}/extensions/strings/extensions_strings_" ] deps += [ "//extensions/strings" ] }
diff --git a/chrome/common/extensions/api/_manifest_features.json b/chrome/common/extensions/api/_manifest_features.json index b1895e75..55bd040 100644 --- a/chrome/common/extensions/api/_manifest_features.json +++ b/chrome/common/extensions/api/_manifest_features.json
@@ -45,15 +45,11 @@ "channel": "stable", "extension_types": ["extension"] }, - "chrome_settings_overrides": [{ + "chrome_settings_overrides": { "channel": "stable", "extension_types": ["extension"], - "platforms": ["win"] - }, { - "channel": "canary", - "extension_types": ["extension"], - "platforms": ["mac"] - }], + "platforms": ["win", "mac"] + }, "chrome_ui_overrides": [{ "channel": "dev", "extension_types": ["extension"]
diff --git a/chrome/common/extensions/extension_process_policy.cc b/chrome/common/extensions/extension_process_policy.cc index 914427763..0bb1591 100644 --- a/chrome/common/extensions/extension_process_policy.cc +++ b/chrome/common/extensions/extension_process_policy.cc
@@ -68,7 +68,11 @@ } bool IsIsolateExtensionsEnabled() { - return true; + const std::string group_name = + base::FieldTrialList::FindFullName("SiteIsolationExtensions"); + bool is_control_group = base::StartsWith( + group_name, "Control", base::CompareCase::INSENSITIVE_ASCII); + return !is_control_group; } } // namespace extensions
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 0893d93..8affd62 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3042,6 +3042,7 @@ "../browser/browsing_data/browsing_data_helper_unittest.cc", "../browser/browsing_data/browsing_data_indexed_db_helper_unittest.cc", "../browser/browsing_data/browsing_data_local_storage_helper_unittest.cc", + "../browser/browsing_data/browsing_data_media_license_helper_unittest.cc", "../browser/browsing_data/browsing_data_quota_helper_unittest.cc", "../browser/browsing_data/browsing_data_remover_test_util.cc", "../browser/browsing_data/browsing_data_remover_test_util.h", @@ -3450,8 +3451,8 @@ "//components/strings", "//components/webdata_services:test_support", "//content/app/resources", + "//device/base:mocks", "//device/bluetooth:mocks", - "//device/core:mocks", "//device/usb:test_support", "//gpu:test_support", "//media:test_support",
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py index 5980461..57987b3 100755 --- a/chrome/test/chromedriver/test/run_py_tests.py +++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -858,7 +858,9 @@ def testGetLogOnClosedWindow(self): self._driver.Load(self.GetHttpUrlForFile('/chromedriver/page_test.html')) + old_handles = self._driver.GetWindowHandles() self._driver.FindElement('id', 'link').Click() + self.WaitForNewWindow(self._driver, old_handles) self._driver.CloseWindow() try: self._driver.GetLog('browser')
diff --git a/chrome/test/data/webui/settings/appearance_page_test.js b/chrome/test/data/webui/settings/appearance_page_test.js index 425f217..4ade4fc 100644 --- a/chrome/test/data/webui/settings/appearance_page_test.js +++ b/chrome/test/data/webui/settings/appearance_page_test.js
@@ -14,25 +14,20 @@ */ var TestAppearanceBrowserProxy = function() { settings.TestBrowserProxy.call(this, [ - 'getResetThemeEnabled', + 'getThemeInfo', 'openWallpaperManager', - 'resetTheme', + 'useDefaultTheme', + 'useSystemTheme', ]); - - /** - * @type {boolean} - * @private - */ - this.allowResetTheme_ = false; }; TestAppearanceBrowserProxy.prototype = { __proto__: settings.TestBrowserProxy.prototype, /** @override */ - getResetThemeEnabled: function() { - this.methodCalled('getResetThemeEnabled'); - return Promise.resolve(this.allowResetTheme_); + getThemeInfo: function(themeId) { + this.methodCalled('getThemeInfo', themeId); + return Promise.resolve({name: 'Sports car red'}); }, /** @override */ @@ -41,18 +36,14 @@ }, /** @override */ - resetTheme: function() { - this.methodCalled('resetTheme'); + useDefaultTheme: function() { + this.methodCalled('useDefaultTheme'); }, - /** - * @param {boolean} isEnabled Whether the user reset the theme. - */ - setAllowResetTheme: function(isEnabled) { - this.allowResetTheme_ = isEnabled; - cr.webUIListenerCallback('reset-theme-enabled-changed', isEnabled); - Polymer.dom.flush(); - } + /** @override */ + useSystemTheme: function() { + this.methodCalled('useSystemTheme'); + }, }; /** @@ -110,7 +101,20 @@ PolymerTest.clearBody(); appearancePage = document.createElement('settings-appearance-page'); + appearancePage.set('prefs', { + extensions: { + theme: { + id: { + value: 'asdf', + }, + use_system: { + value: false, + }, + }, + }, + }); document.body.appendChild(appearancePage); + Polymer.dom.flush(); }); teardown(function() { appearancePage.remove(); }); @@ -130,13 +134,21 @@ }); } - test('resetTheme', function() { - appearanceBrowserProxy.setAllowResetTheme(true); - var button = appearancePage.$$('#resetTheme'); + test('useDefaultTheme', function() { + var button = appearancePage.$$('#useDefault'); assertTrue(!!button); MockInteractions.tap(button); - return appearanceBrowserProxy.whenCalled('resetTheme'); + return appearanceBrowserProxy.whenCalled('useDefaultTheme'); }); + + if (cr.isLinux && !cr.isChromeOS) { + test('useSystemTheme', function() { + var button = appearancePage.$$('#useSystem'); + assertTrue(!!button); + MockInteractions.tap(button); + return appearanceBrowserProxy.whenCalled('useSystemTheme'); + }); + } }); }
diff --git a/chrome_elf/BUILD.gn b/chrome_elf/BUILD.gn index 14eafbb..0629b6f 100644 --- a/chrome_elf/BUILD.gn +++ b/chrome_elf/BUILD.gn
@@ -52,6 +52,9 @@ configs += [ "//build/config/win:windowed" ] configs -= [ "//build/config/win:console" ] + # Turn on CFG for this project. + configs += [ "//build/config/win:win_msvc_cfg" ] + # Delay loads in this list will prevent user32.dll # from loading too early. ldflags = [
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn index 5833318..47d963e1 100644 --- a/chromecast/BUILD.gn +++ b/chromecast/BUILD.gn
@@ -197,7 +197,13 @@ net_unittests_filter = { test_name = "net_unittests" - if (target_os == "linux" && !is_cast_desktop_build) { + if (using_sanitizer) { + # TODO(mbjorge): net_unittests do not complete when run with sanitizers, + # (in particular, TSAN and UBSAN), resulting in build machines getting stuck + # for many hours. Disable them for now, since these are getting run on + # Chromium bots anyway. (internal b/31279943) + gtest_excludes = [ "*" ] + } else if (target_os == "linux" && !is_cast_desktop_build) { # Run net_unittests first to avoid random failures due to slow python startup # KeygenHandlerTest.SmokeTest and KeygenHandlerTest.ConcurrencyTest fail due to # readonly certdb (b/8153161) @@ -230,15 +236,6 @@ } } filters += [ net_unittests_filter ] - - # TODO(mbjorge): net_unittests do not complete when run with sanitizers, - # (in particular, TSAN and UBSAN), resulting in build machines getting stuck - # for many hours. Disable them for now, since these are getting run on - # Chromium bots anyway. (internal b/31279943) - if (using_sanitizer) { - tests -= [ "//net:net_unittests" ] - filters -= [ net_unittests_filter ] - } } # Creates the build and run lists for all test targets.
diff --git a/chromeos/dbus/fake_power_manager_client.cc b/chromeos/dbus/fake_power_manager_client.cc index dcb82fa..1bcbee1 100644 --- a/chromeos/dbus/fake_power_manager_client.cc +++ b/chromeos/dbus/fake_power_manager_client.cc
@@ -24,6 +24,7 @@ num_set_is_projecting_calls_(0), num_pending_suspend_readiness_callbacks_(0), is_projecting_(false), + backlights_forced_off_(false), weak_ptr_factory_(this) { } @@ -134,6 +135,16 @@ NotifyObservers(); } +void FakePowerManagerClient::SetBacklightsForcedOff(bool forced_off) { + backlights_forced_off_ = forced_off; +} + +void FakePowerManagerClient::GetBacklightsForcedOff( + const GetBacklightsForcedOffCallback& callback) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(callback, backlights_forced_off_)); +} + base::Closure FakePowerManagerClient::GetSuspendReadinessCallback() { ++num_pending_suspend_readiness_callbacks_;
diff --git a/chromeos/dbus/fake_power_manager_client.h b/chromeos/dbus/fake_power_manager_client.h index fc6bbae..14eca3c3 100644 --- a/chromeos/dbus/fake_power_manager_client.h +++ b/chromeos/dbus/fake_power_manager_client.h
@@ -63,6 +63,9 @@ void SetPolicy(const power_manager::PowerManagementPolicy& policy) override; void SetIsProjecting(bool is_projecting) override; void SetPowerSource(const std::string& id) override; + void SetBacklightsForcedOff(bool forced_off) override; + void GetBacklightsForcedOff( + const GetBacklightsForcedOffCallback& callback) override; base::Closure GetSuspendReadinessCallback() override; int GetNumPendingSuspendReadinessCallbacks() override; @@ -111,6 +114,10 @@ // Last projecting state set in SetIsProjecting(). bool is_projecting_; + // Display and keyboard backlights (if present) forced off state set in + // SetBacklightsForcedOff(). + bool backlights_forced_off_; + // Video activity reports that we were requested to send, in the order they // were requested. True if fullscreen. std::deque<bool> video_activity_reports_;
diff --git a/chromeos/dbus/fake_shill_manager_client.cc b/chromeos/dbus/fake_shill_manager_client.cc index 047c4f1..a4df88b 100644 --- a/chromeos/dbus/fake_shill_manager_client.cc +++ b/chromeos/dbus/fake_shill_manager_client.cc
@@ -457,7 +457,7 @@ list_value = new base::ListValue; stub_geo_networks_.SetWithoutPathExpansion(technology, list_value); } - list_value->Append(network.DeepCopy()); + list_value->Append(network.CreateDeepCopy()); } void FakeShillManagerClient::AddProfile(const std::string& profile_path) { @@ -867,8 +867,8 @@ services->SetServiceProperty(kCellularServicePath, shill::kCellularLastGoodApnProperty, apn); base::ListValue apn_list; - apn_list.Append(apn.DeepCopy()); - apn_list.Append(apn2.DeepCopy()); + apn_list.Append(apn.CreateDeepCopy()); + apn_list.Append(apn2.CreateDeepCopy()); devices->SetDeviceProperty("/device/cellular1", shill::kCellularApnListProperty, apn_list); @@ -1041,7 +1041,7 @@ std::string type; properties->GetString(shill::kTypeProperty, &type); if (TechnologyEnabled(type)) - new_service_list->Append((*iter)->DeepCopy()); + new_service_list->Append((*iter)->CreateDeepCopy()); } } return new_service_list;
diff --git a/chromeos/dbus/power_manager_client.cc b/chromeos/dbus/power_manager_client.cc index 3186f2ff..2d8291e1 100644 --- a/chromeos/dbus/power_manager_client.cc +++ b/chromeos/dbus/power_manager_client.cc
@@ -89,9 +89,6 @@ void SetRenderProcessManagerDelegate( base::WeakPtr<RenderProcessManagerDelegate> delegate) override { - // TODO(derat): Remove after http://crbug.com/648580 is fixed. - VLOG(1) << "Setting RenderProcessManagerDelegate to " << delegate.get(); - VLOG(1) << "vtable is " << *reinterpret_cast<uintptr_t*>(delegate.get()); DCHECK(!render_process_manager_delegate_) << "There can be only one! ...RenderProcessManagerDelegate"; render_process_manager_delegate_ = delegate; @@ -246,6 +243,25 @@ dbus::ObjectProxy::EmptyResponseCallback()); } + void SetBacklightsForcedOff(bool forced_off) override { + dbus::MethodCall method_call(power_manager::kPowerManagerInterface, + power_manager::kSetBacklightsForcedOffMethod); + dbus::MessageWriter(&method_call).AppendBool(forced_off); + power_manager_proxy_->CallMethod( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + dbus::ObjectProxy::EmptyResponseCallback()); + } + + void GetBacklightsForcedOff( + const GetBacklightsForcedOffCallback& callback) override { + dbus::MethodCall method_call(power_manager::kPowerManagerInterface, + power_manager::kGetBacklightsForcedOffMethod); + power_manager_proxy_->CallMethod( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&PowerManagerClientImpl::OnGetBacklightsForcedOff, + weak_ptr_factory_.GetWeakPtr(), callback)); + } + base::Closure GetSuspendReadinessCallback() override { DCHECK(OnOriginThread()); DCHECK(suspend_is_pending_); @@ -471,12 +487,29 @@ } dbus::MessageReader reader(response); double percent = 0.0; - if (!reader.PopDouble(&percent)) + if (!reader.PopDouble(&percent)) { POWER_LOG(ERROR) << "Error reading response from powerd: " << response->ToString(); + } callback.Run(percent); } + void OnGetBacklightsForcedOff(const GetBacklightsForcedOffCallback& callback, + dbus::Response* response) { + if (!response) { + POWER_LOG(ERROR) << "Error calling " + << power_manager::kGetBacklightsForcedOffMethod; + return; + } + dbus::MessageReader reader(response); + bool state = false; + if (!reader.PopBool(&state)) { + POWER_LOG(ERROR) << "Error reading response from powerd: " + << response->ToString(); + } + callback.Run(state); + } + void HandlePowerSupplyProperties( const power_manager::PowerSupplyProperties& proto) { FOR_EACH_OBSERVER(Observer, observers_, PowerChanged(proto)); @@ -528,10 +561,9 @@ return; } - // TODO(derat): Switch back to POWER_LOG(EVENT) after - // http://crbug.com/648580 is fixed. - VLOG(1) << "Got " << signal_name << " signal announcing suspend attempt " - << proto.suspend_id(); + POWER_LOG(EVENT) << "Got " << signal_name + << " signal announcing suspend attempt " + << proto.suspend_id(); // If a previous suspend is pending from the same state we are currently in // (fully powered on or in dark resume), then something's gone a little @@ -575,31 +607,19 @@ const base::TimeDelta duration = base::TimeDelta::FromInternalValue(proto.suspend_duration()); - // TODO(derat): Switch back to POWER_LOG(EVENT) after - // http://crbug.com/648580 is fixed. - VLOG(1) << "Got " << power_manager::kSuspendDoneSignal << " signal:" - << " suspend_id=" << proto.suspend_id() - << " duration=" << duration.InSeconds() << " sec"; + POWER_LOG(EVENT) << "Got " << power_manager::kSuspendDoneSignal + << " signal:" + << " suspend_id=" << proto.suspend_id() + << " duration=" << duration.InSeconds() << " sec"; // RenderProcessManagerDelegate is only notified that suspend is imminent // when readiness is being reported to powerd. If the suspend attempt was // cancelled before then, we shouldn't notify the delegate about completion. const bool cancelled_while_regular_suspend_pending = suspend_is_pending_ && !suspending_from_dark_resume_; - // TODO(derat): Remove VLOG(1)s after http://crbug.com/648580 is fixed. - VLOG(1) << "RenderProcessManagerDelegate is " - << render_process_manager_delegate_.get() << "; suspend is" - << (suspend_is_pending_ ? "" : "n't") << " pending and was" - << (suspending_from_dark_resume_ ? "" : "n't") - << " suspending from dark resume"; if (render_process_manager_delegate_ && - !cancelled_while_regular_suspend_pending) { - VLOG(1) << "Calling RenderProcessManagerDelegate::SuspendDone()"; - VLOG(1) << "vtable is " - << *reinterpret_cast<uintptr_t*>( - render_process_manager_delegate_.get()); + !cancelled_while_regular_suspend_pending) render_process_manager_delegate_->SuspendDone(); - } // powerd always pairs each SuspendImminent signal with SuspendDone before // starting the next suspend attempt, so we should no longer report @@ -739,10 +759,6 @@ // GetSuspendReadinessCallback(). void HandleObserverSuspendReadiness(int32_t suspend_id, bool in_dark_resume) { DCHECK(OnOriginThread()); - // TODO(derat): Remove after http://crbug.com/648580 is fixed. - VLOG(1) << "Got notification of observer readiness for " - << (in_dark_resume ? "dark" : "regular") << " suspend ID " - << suspend_id << " (pending " << pending_suspend_id_ << ")"; if (!suspend_is_pending_ || suspend_id != pending_suspend_id_ || in_dark_resume != suspending_from_dark_resume_) return; @@ -761,12 +777,8 @@ if (notifying_observers_about_suspend_imminent_) return; - if (num_pending_suspend_readiness_callbacks_ > 0) { - // TODO(derat): Remove after http://crbug.com/648580 is fixed. - VLOG(1) << "Not reporting suspend readiness; waiting for " - << num_pending_suspend_readiness_callbacks_ << " callback(s)"; + if (num_pending_suspend_readiness_callbacks_ > 0) return; - } std::string method_name; int32_t delay_id = -1; @@ -778,27 +790,15 @@ delay_id = suspend_delay_id_; } - // TODO(derat): Remove VLOG(1)s after http://crbug.com/648580 is fixed. - VLOG(1) << "RenderProcessManagerDelegate is " - << render_process_manager_delegate_.get() << "; " - << (suspending_from_dark_resume_ ? "" : "not ") - << "suspending from dark resume"; - if (render_process_manager_delegate_ && !suspending_from_dark_resume_) { - VLOG(1) << "Calling RenderProcessManagerDelegate::SuspendImminent()"; - VLOG(1) << "vtable is " - << *reinterpret_cast<uintptr_t*>( - render_process_manager_delegate_.get()); + if (render_process_manager_delegate_ && !suspending_from_dark_resume_) render_process_manager_delegate_->SuspendImminent(); - } dbus::MethodCall method_call( power_manager::kPowerManagerInterface, method_name); dbus::MessageWriter writer(&method_call); - // TODO(derat): Switch back to POWER_LOG(EVENT) after - // http://crbug.com/648580 is fixed. - VLOG(1) << "Announcing readiness of suspend delay " << delay_id - << " for suspend attempt " << pending_suspend_id_; + POWER_LOG(EVENT) << "Announcing readiness of suspend delay " << delay_id + << " for suspend attempt " << pending_suspend_id_; power_manager::SuspendReadinessInfo protobuf_request; protobuf_request.set_delay_id(delay_id); protobuf_request.set_suspend_id(pending_suspend_id_);
diff --git a/chromeos/dbus/power_manager_client.h b/chromeos/dbus/power_manager_client.h index f4d9ada0..9f341deb 100644 --- a/chromeos/dbus/power_manager_client.h +++ b/chromeos/dbus/power_manager_client.h
@@ -27,6 +27,9 @@ // range [0.0, 100.0]. typedef base::Callback<void(double)> GetScreenBrightnessPercentCallback; +// Callback used for getting the current backlights forced off state. +typedef base::Callback<void(bool)> GetBacklightsForcedOffCallback; + // PowerManagerClient is used to communicate with the power manager. class CHROMEOS_EXPORT PowerManagerClient : public DBusClient { public: @@ -184,6 +187,13 @@ // causes powerd to switch to using the battery on devices with type-C ports. virtual void SetPowerSource(const std::string& id) = 0; + // Forces the display and keyboard backlights (if present) to |forced_off|. + virtual void SetBacklightsForcedOff(bool forced_off) = 0; + + // Gets the display and keyboard backlights (if present) forced off state. + virtual void GetBacklightsForcedOff( + const GetBacklightsForcedOffCallback& callback) = 0; + // Returns a callback that can be called by an observer to report // readiness for suspend. See Observer::SuspendImminent(). virtual base::Closure GetSuspendReadinessCallback() = 0;
diff --git a/chromeos/geolocation/simple_geolocation_request.cc b/chromeos/geolocation/simple_geolocation_request.cc index 1d5ce4a..cb10cd6 100644 --- a/chromeos/geolocation/simple_geolocation_request.cc +++ b/chromeos/geolocation/simple_geolocation_request.cc
@@ -8,9 +8,11 @@ #include <algorithm> #include <string> +#include <utility> #include "base/json/json_reader.h" #include "base/json/json_writer.h" +#include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/sparse_histogram.h" #include "base/strings/string_number_conversions.h" @@ -332,8 +334,7 @@ request->SetWithoutPathExpansion(kWifiAccessPoints, wifi_access_points); for (const WifiAccessPoint& access_point : *wifi_data_) { - base::DictionaryValue* access_point_dictionary = new base::DictionaryValue; - wifi_access_points->Append(access_point_dictionary); + auto access_point_dictionary = base::MakeUnique<base::DictionaryValue>(); access_point_dictionary->SetStringWithoutPathExpansion( kMacAddress, access_point.mac_address); @@ -350,6 +351,8 @@ kChannel, access_point.channel); access_point_dictionary->SetIntegerWithoutPathExpansion( kSignalToNoiseRatio, access_point.signal_to_noise); + + wifi_access_points->Append(std::move(access_point_dictionary)); } std::string result; if (!base::JSONWriter::Write(*request, &result)) {
diff --git a/chromeos/network/managed_network_configuration_handler_impl.cc b/chromeos/network/managed_network_configuration_handler_impl.cc index dd46255..71eed8b 100644 --- a/chromeos/network/managed_network_configuration_handler_impl.cc +++ b/chromeos/network/managed_network_configuration_handler_impl.cc
@@ -768,7 +768,7 @@ base::ListValue* ip_configs = new base::ListValue; for (base::DictionaryValue::Iterator iter(device_state->ip_configs()); !iter.IsAtEnd(); iter.Advance()) { - ip_configs->Append(iter.value().DeepCopy()); + ip_configs->Append(iter.value().CreateDeepCopy()); } properties->SetWithoutPathExpansion(shill::kIPConfigsProperty, ip_configs); }
diff --git a/components/arc/arc_bridge_bootstrap.h b/components/arc/arc_bridge_bootstrap.h index 45d2d72..c9f6dd7 100644 --- a/components/arc/arc_bridge_bootstrap.h +++ b/components/arc/arc_bridge_bootstrap.h
@@ -12,7 +12,6 @@ #include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" #include "components/arc/arc_bridge_service.h" -#include "components/arc/common/arc_bridge.mojom.h" namespace arc {
diff --git a/components/arc/arc_bridge_service.h b/components/arc/arc_bridge_service.h index d3ee567..040f890 100644 --- a/components/arc/arc_bridge_service.h +++ b/components/arc/arc_bridge_service.h
@@ -14,7 +14,6 @@ #include "base/macros.h" #include "base/observer_list.h" #include "base/values.h" -#include "components/arc/common/arc_bridge.mojom.h" #include "components/arc/instance_holder.h" namespace base { @@ -25,6 +24,36 @@ class ArcBridgeTest; +namespace mojom { + +// Instead of including components/arc/common/arc_bridge.mojom.h, list all the +// instance classes here for faster build. +class AppInstance; +class AudioInstance; +class AuthInstance; +class BluetoothInstance; +class BootPhaseMonitorInstance; +class ClipboardInstance; +class CrashCollectorInstance; +class EnterpriseReportingInstance; +class FileSystemInstance; +class ImeInstance; +class IntentHelperInstance; +class MetricsInstance; +class NetInstance; +class NotificationsInstance; +class ObbMounterInstance; +class PolicyInstance; +class PowerInstance; +class PrintInstance; +class ProcessInstance; +class StorageManagerInstance; +class TtsInstance; +class VideoInstance; +class WallpaperInstance; + +} // namespace mojom + // The Chrome-side service that handles ARC instances and ARC bridge creation. // This service handles the lifetime of ARC instances and sets up the // communication channel (the ARC bridge) used to send and receive messages.
diff --git a/components/arc/audio/arc_audio_bridge.cc b/components/arc/audio/arc_audio_bridge.cc index 02f4cec..69d4563 100644 --- a/components/arc/audio/arc_audio_bridge.cc +++ b/components/arc/audio/arc_audio_bridge.cc
@@ -8,6 +8,7 @@ #include "ash/common/wm_shell.h" #include "base/logging.h" #include "chromeos/audio/audio_device.h" +#include "components/arc/arc_bridge_service.h" namespace arc {
diff --git a/components/arc/audio/arc_audio_bridge.h b/components/arc/audio/arc_audio_bridge.h index 34cf4f1..56c516c2f 100644 --- a/components/arc/audio/arc_audio_bridge.h +++ b/components/arc/audio/arc_audio_bridge.h
@@ -9,13 +9,15 @@ #include "base/macros.h" #include "chromeos/audio/cras_audio_handler.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/common/audio.mojom.h" #include "components/arc/instance_holder.h" #include "mojo/public/cpp/bindings/binding.h" namespace arc { +class ArcBridgeService; + class ArcAudioBridge : public ArcService, public InstanceHolder<mojom::AudioInstance>::Observer, public mojom::AudioHost,
diff --git a/components/arc/bluetooth/arc_bluetooth_bridge.h b/components/arc/bluetooth/arc_bluetooth_bridge.h index f3a3c66..aeb2f854 100644 --- a/components/arc/bluetooth/arc_bluetooth_bridge.h +++ b/components/arc/bluetooth/arc_bluetooth_bridge.h
@@ -7,6 +7,7 @@ #include <stdint.h> +#include <map> #include <memory> #include <string> #include <unordered_map> @@ -15,7 +16,6 @@ #include "base/callback.h" #include "base/timer/timer.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" #include "components/arc/common/bluetooth.mojom.h" #include "components/arc/instance_holder.h"
diff --git a/components/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.cc b/components/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.cc index e4698df7..e4af76af 100644 --- a/components/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.cc +++ b/components/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.cc
@@ -7,6 +7,7 @@ #include "base/logging.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/session_manager_client.h" +#include "components/arc/arc_bridge_service.h" namespace arc {
diff --git a/components/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.h b/components/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.h index 8c783ba..b42137d 100644 --- a/components/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.h +++ b/components/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.h
@@ -7,7 +7,6 @@ #include "base/macros.h" #include "base/threading/thread_checker.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" #include "components/arc/common/boot_phase_monitor.mojom.h" #include "components/arc/instance_holder.h" @@ -15,6 +14,8 @@ namespace arc { +class ArcBridgeService; + // Receives boot phase notifications from ARC. class ArcBootPhaseMonitorBridge : public ArcService, @@ -28,7 +29,7 @@ void OnInstanceReady() override; void OnInstanceClosed() override; - // arc::mojom::BootPhaseMonitorHost + // mojom::BootPhaseMonitorHost void OnBootCompleted() override; private:
diff --git a/components/arc/clipboard/arc_clipboard_bridge.cc b/components/arc/clipboard/arc_clipboard_bridge.cc index 029b1ad..de6ad414 100644 --- a/components/arc/clipboard/arc_clipboard_bridge.cc +++ b/components/arc/clipboard/arc_clipboard_bridge.cc
@@ -4,11 +4,10 @@ #include "components/arc/clipboard/arc_clipboard_bridge.h" -#include <utility> - #include "base/logging.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_checker.h" +#include "components/arc/arc_bridge_service.h" #include "ui/base/clipboard/clipboard.h" #include "ui/base/clipboard/clipboard_types.h" #include "ui/base/clipboard/scoped_clipboard_writer.h"
diff --git a/components/arc/clipboard/arc_clipboard_bridge.h b/components/arc/clipboard/arc_clipboard_bridge.h index 97a569d..3b105e2 100644 --- a/components/arc/clipboard/arc_clipboard_bridge.h +++ b/components/arc/clipboard/arc_clipboard_bridge.h
@@ -5,13 +5,12 @@ #ifndef COMPONENTS_ARC_CLIPBOARD_ARC_CLIPBOARD_BRIDGE_H_ #define COMPONENTS_ARC_CLIPBOARD_ARC_CLIPBOARD_BRIDGE_H_ -#include <string> - #include "base/macros.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/common/clipboard.mojom.h" #include "components/arc/instance_holder.h" #include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/string.h" namespace arc {
diff --git a/components/arc/crash_collector/arc_crash_collector_bridge.cc b/components/arc/crash_collector/arc_crash_collector_bridge.cc index 3114077..1f55f314 100644 --- a/components/arc/crash_collector/arc_crash_collector_bridge.cc +++ b/components/arc/crash_collector/arc_crash_collector_bridge.cc
@@ -11,6 +11,7 @@ #include "base/logging.h" #include "base/process/launch.h" +#include "components/arc/arc_bridge_service.h" #include "mojo/edk/embedder/embedder.h" namespace {
diff --git a/components/arc/crash_collector/arc_crash_collector_bridge.h b/components/arc/crash_collector/arc_crash_collector_bridge.h index 0b7ec56..6bc78c49 100644 --- a/components/arc/crash_collector/arc_crash_collector_bridge.h +++ b/components/arc/crash_collector/arc_crash_collector_bridge.h
@@ -9,17 +9,20 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/common/crash_collector.mojom.h" #include "components/arc/instance_holder.h" #include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/string.h" namespace base { class TaskRunner; -} +} // namespace base namespace arc { +class ArcBridgeService; + // Relays dumps for non-native ARC crashes to the crash reporter in Chrome OS. class ArcCrashCollectorBridge : public ArcService,
diff --git a/components/arc/ime/arc_ime_bridge_impl.cc b/components/arc/ime/arc_ime_bridge_impl.cc index 224580f3..6faa6f3 100644 --- a/components/arc/ime/arc_ime_bridge_impl.cc +++ b/components/arc/ime/arc_ime_bridge_impl.cc
@@ -19,51 +19,49 @@ constexpr uint32_t kMinVersionForOnKeyboardsBoundsChanging = 3; constexpr uint32_t kMinVersionForExtendSelectionAndDelete = 4; -ui::TextInputType ConvertTextInputType(arc::mojom::TextInputType ipc_type) { +ui::TextInputType ConvertTextInputType(mojom::TextInputType ipc_type) { // The two enum types are similar, but intentionally made not identical. // We cannot force them to be in sync. If we do, updates in ui::TextInputType - // must always be propagated to the arc::mojom::TextInputType mojo definition - // in + // must always be propagated to the mojom::TextInputType mojo definition in // ARC container side, which is in a different repository than Chromium. // We don't want such dependency. // // That's why we need a lengthy switch statement instead of static_cast // guarded by a static assert on the two enums to be in sync. switch (ipc_type) { - case arc::mojom::TextInputType::NONE: + case mojom::TextInputType::NONE: return ui::TEXT_INPUT_TYPE_NONE; - case arc::mojom::TextInputType::TEXT: + case mojom::TextInputType::TEXT: return ui::TEXT_INPUT_TYPE_TEXT; - case arc::mojom::TextInputType::PASSWORD: + case mojom::TextInputType::PASSWORD: return ui::TEXT_INPUT_TYPE_PASSWORD; - case arc::mojom::TextInputType::SEARCH: + case mojom::TextInputType::SEARCH: return ui::TEXT_INPUT_TYPE_SEARCH; - case arc::mojom::TextInputType::EMAIL: + case mojom::TextInputType::EMAIL: return ui::TEXT_INPUT_TYPE_EMAIL; - case arc::mojom::TextInputType::NUMBER: + case mojom::TextInputType::NUMBER: return ui::TEXT_INPUT_TYPE_NUMBER; - case arc::mojom::TextInputType::TELEPHONE: + case mojom::TextInputType::TELEPHONE: return ui::TEXT_INPUT_TYPE_TELEPHONE; - case arc::mojom::TextInputType::URL: + case mojom::TextInputType::URL: return ui::TEXT_INPUT_TYPE_URL; - case arc::mojom::TextInputType::DATE: + case mojom::TextInputType::DATE: return ui::TEXT_INPUT_TYPE_DATE; - case arc::mojom::TextInputType::TIME: + case mojom::TextInputType::TIME: return ui::TEXT_INPUT_TYPE_TIME; - case arc::mojom::TextInputType::DATETIME: + case mojom::TextInputType::DATETIME: return ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL; default: return ui::TEXT_INPUT_TYPE_TEXT; } } -mojo::Array<arc::mojom::CompositionSegmentPtr> ConvertSegments( +mojo::Array<mojom::CompositionSegmentPtr> ConvertSegments( const ui::CompositionText& composition) { - mojo::Array<arc::mojom::CompositionSegmentPtr> segments = - mojo::Array<arc::mojom::CompositionSegmentPtr>::New(0); + mojo::Array<mojom::CompositionSegmentPtr> segments = + mojo::Array<mojom::CompositionSegmentPtr>::New(0); for (const ui::CompositionUnderline& underline : composition.underlines) { - arc::mojom::CompositionSegmentPtr segment = - arc::mojom::CompositionSegment::New(); + mojom::CompositionSegmentPtr segment = mojom::CompositionSegment::New(); segment->start_offset = underline.start_offset; segment->end_offset = underline.end_offset; segment->emphasized = @@ -142,11 +140,11 @@ ime_instance->ExtendSelectionAndDelete(before, after); } -void ArcImeBridgeImpl::OnTextInputTypeChanged(arc::mojom::TextInputType type) { +void ArcImeBridgeImpl::OnTextInputTypeChanged(mojom::TextInputType type) { delegate_->OnTextInputTypeChanged(ConvertTextInputType(type)); } -void ArcImeBridgeImpl::OnCursorRectChanged(arc::mojom::CursorRectPtr rect) { +void ArcImeBridgeImpl::OnCursorRectChanged(mojom::CursorRectPtr rect) { delegate_->OnCursorRectChanged(gfx::Rect(rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top));
diff --git a/components/arc/ime/arc_ime_bridge_impl.h b/components/arc/ime/arc_ime_bridge_impl.h index 2246e52..548a8da 100644 --- a/components/arc/ime/arc_ime_bridge_impl.h +++ b/components/arc/ime/arc_ime_bridge_impl.h
@@ -7,7 +7,6 @@ #include "base/macros.h" #include "base/strings/string16.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/common/ime.mojom.h" #include "components/arc/ime/arc_ime_bridge.h" #include "components/arc/instance_holder.h" @@ -21,6 +20,8 @@ namespace arc { +class ArcBridgeService; + // This class encapsulates the detail of IME related IPC between // Chromium and the ARC container. class ArcImeBridgeImpl : public ArcImeBridge, @@ -30,7 +31,7 @@ ArcImeBridgeImpl(Delegate* delegate, ArcBridgeService* bridge_service); ~ArcImeBridgeImpl() override; - // arc::InstanceHolder<mojom::ImeInstance>::Observer overrides: + // InstanceHolder<mojom::ImeInstance>::Observer overrides: void OnInstanceReady() override; // ArcImeBridge overrides: @@ -40,9 +41,9 @@ void SendOnKeyboardBoundsChanging(const gfx::Rect& new_bounds) override; void SendExtendSelectionAndDelete(size_t before, size_t after) override; - // arc::mojom::ImeHost overrides: - void OnTextInputTypeChanged(arc::mojom::TextInputType type) override; - void OnCursorRectChanged(arc::mojom::CursorRectPtr rect) override; + // mojom::ImeHost overrides: + void OnTextInputTypeChanged(mojom::TextInputType type) override; + void OnCursorRectChanged(mojom::CursorRectPtr rect) override; void OnCancelComposition() override; void ShowImeIfNeeded() override;
diff --git a/components/arc/intent_helper/arc_intent_helper_bridge.cc b/components/arc/intent_helper/arc_intent_helper_bridge.cc index e7af4fa..2a8c33d2 100644 --- a/components/arc/intent_helper/arc_intent_helper_bridge.cc +++ b/components/arc/intent_helper/arc_intent_helper_bridge.cc
@@ -14,6 +14,7 @@ #include "ash/shell.h" #include "base/command_line.h" #include "base/memory/weak_ptr.h" +#include "components/arc/arc_bridge_service.h" #include "components/arc/intent_helper/activity_icon_loader.h" #include "components/arc/intent_helper/link_handler_model_impl.h" #include "components/arc/intent_helper/local_activity_resolver.h"
diff --git a/components/arc/intent_helper/arc_intent_helper_bridge.h b/components/arc/intent_helper/arc_intent_helper_bridge.h index fbc2f92..92d9a70 100644 --- a/components/arc/intent_helper/arc_intent_helper_bridge.h +++ b/components/arc/intent_helper/arc_intent_helper_bridge.h
@@ -12,7 +12,6 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/threading/thread_checker.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" #include "components/arc/common/intent_helper.mojom.h" #include "components/arc/instance_holder.h" @@ -27,6 +26,7 @@ namespace arc { class ActivityIconLoader; +class ArcBridgeService; class LocalActivityResolver; class SetWallpaperDelegate; @@ -56,7 +56,7 @@ void OnInstanceReady() override; void OnInstanceClosed() override; - // arc::mojom::IntentHelperHost + // mojom::IntentHelperHost void OnIconInvalidated(const mojo::String& package_name) override; void OnIntentFiltersUpdated( mojo::Array<mojom::IntentFilterPtr> intent_filters) override;
diff --git a/components/arc/metrics/arc_metrics_service.cc b/components/arc/metrics/arc_metrics_service.cc index bb4cf9d..8ee9160 100644 --- a/components/arc/metrics/arc_metrics_service.cc +++ b/components/arc/metrics/arc_metrics_service.cc
@@ -12,6 +12,7 @@ #include "base/strings/string_util.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/session_manager_client.h" +#include "components/arc/arc_bridge_service.h" namespace { @@ -86,7 +87,7 @@ } void ArcMetricsService::ParseProcessList( - mojo::Array<arc::mojom::RunningAppProcessInfoPtr> processes) { + mojo::Array<mojom::RunningAppProcessInfoPtr> processes) { int running_app_count = 0; for (const auto& process : processes) { const mojo::String& process_name = process->process_name; @@ -137,7 +138,7 @@ } void ArcMetricsService::ReportBootProgress( - mojo::Array<arc::mojom::BootProgressEventPtr> events) { + mojo::Array<mojom::BootProgressEventPtr> events) { DCHECK(CalledOnValidThread()); int64_t arc_start_time_in_ms = (arc_start_time_ - base::TimeTicks()).InMilliseconds();
diff --git a/components/arc/metrics/arc_metrics_service.h b/components/arc/metrics/arc_metrics_service.h index 06fdf7b..c240fda6 100644 --- a/components/arc/metrics/arc_metrics_service.h +++ b/components/arc/metrics/arc_metrics_service.h
@@ -9,15 +9,17 @@ #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" #include "base/timer/timer.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" -#include "components/arc/common/arc_bridge.mojom.h" +#include "components/arc/common/metrics.mojom.h" +#include "components/arc/common/process.mojom.h" #include "components/arc/instance_holder.h" #include "components/arc/metrics/oom_kills_monitor.h" #include "mojo/public/cpp/bindings/binding.h" namespace arc { +class ArcBridgeService; + // Collects information from other ArcServices and send UMA metrics. class ArcMetricsService : public ArcService, @@ -37,13 +39,12 @@ // MetricsHost overrides. void ReportBootProgress( - mojo::Array<arc::mojom::BootProgressEventPtr> events) override; + mojo::Array<mojom::BootProgressEventPtr> events) override; private: bool CalledOnValidThread(); void RequestProcessList(); - void ParseProcessList( - mojo::Array<arc::mojom::RunningAppProcessInfoPtr> processes); + void ParseProcessList(mojo::Array<mojom::RunningAppProcessInfoPtr> processes); // DBus callbacks. void OnArcStartTimeRetrieved(bool success, base::TimeTicks arc_start_time);
diff --git a/components/arc/metrics/oom_kills_monitor.h b/components/arc/metrics/oom_kills_monitor.h index f4e188445..63e249e 100644 --- a/components/arc/metrics/oom_kills_monitor.h +++ b/components/arc/metrics/oom_kills_monitor.h
@@ -50,7 +50,7 @@ void Run() override; // A flag set when OomKillsMonitor is shutdown so that its thread can poll - // it and attempt to wind down from that point (to avoid unecessary work, not + // it and attempt to wind down from that point (to avoid unnecessary work, not // because it blocks shutdown). base::AtomicFlag is_shutting_down_;
diff --git a/components/arc/net/arc_net_host_impl.cc b/components/arc/net/arc_net_host_impl.cc index a0f3c6c..be17b60c 100644 --- a/components/arc/net/arc_net_host_impl.cc +++ b/components/arc/net/arc_net_host_impl.cc
@@ -413,7 +413,7 @@ } void ArcNetHostImpl::CreateNetworkSuccessCallback( - const arc::mojom::NetHost::CreateNetworkCallback& mojo_callback, + const mojom::NetHost::CreateNetworkCallback& mojo_callback, const std::string& service_path, const std::string& guid) { VLOG(1) << "CreateNetworkSuccessCallback"; @@ -425,7 +425,7 @@ } void ArcNetHostImpl::CreateNetworkFailureCallback( - const arc::mojom::NetHost::CreateNetworkCallback& mojo_callback, + const mojom::NetHost::CreateNetworkCallback& mojo_callback, const std::string& error_name, std::unique_ptr<base::DictionaryValue> error_data) { VLOG(1) << "CreateNetworkFailureCallback: " << error_name; @@ -630,7 +630,7 @@ std::string user_id_hash = chromeos::LoginState::Get()->primary_user_hash(); GetManagedConfigurationHandler()->GetProperties( user_id_hash, network->path(), - base::Bind(&arc::ArcNetHostImpl::DefaultNetworkSuccessCallback, + base::Bind(&ArcNetHostImpl::DefaultNetworkSuccessCallback, weak_factory_.GetWeakPtr()), base::Bind(&DefaultNetworkFailureCallback)); }
diff --git a/components/arc/net/arc_net_host_impl.h b/components/arc/net/arc_net_host_impl.h index ae2452b..58248c8 100644 --- a/components/arc/net/arc_net_host_impl.h +++ b/components/arc/net/arc_net_host_impl.h
@@ -15,7 +15,6 @@ #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" #include "chromeos/network/network_state_handler_observer.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" #include "components/arc/common/net.mojom.h" #include "components/arc/instance_holder.h" @@ -95,12 +94,12 @@ bool GetNetworkPathFromGuid(const std::string& guid, std::string* path); void CreateNetworkSuccessCallback( - const arc::mojom::NetHost::CreateNetworkCallback& mojo_callback, + const mojom::NetHost::CreateNetworkCallback& mojo_callback, const std::string& service_path, const std::string& guid); void CreateNetworkFailureCallback( - const arc::mojom::NetHost::CreateNetworkCallback& mojo_callback, + const mojom::NetHost::CreateNetworkCallback& mojo_callback, const std::string& error_name, std::unique_ptr<base::DictionaryValue> error_data); @@ -108,7 +107,7 @@ std::string cached_guid_; base::ThreadChecker thread_checker_; - mojo::Binding<arc::mojom::NetHost> binding_; + mojo::Binding<mojom::NetHost> binding_; base::WeakPtrFactory<ArcNetHostImpl> weak_factory_; DISALLOW_COPY_AND_ASSIGN(ArcNetHostImpl);
diff --git a/components/arc/obb_mounter/arc_obb_mounter_bridge.h b/components/arc/obb_mounter/arc_obb_mounter_bridge.h index 6b5e3fcc..30d162a 100644 --- a/components/arc/obb_mounter/arc_obb_mounter_bridge.h +++ b/components/arc/obb_mounter/arc_obb_mounter_bridge.h
@@ -6,13 +6,15 @@ #define COMPONENTS_ARC_OBB_MOUNTER_ARC_OBB_MOUNTER_BRIDGE_H_ #include "base/macros.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/common/obb_mounter.mojom.h" #include "components/arc/instance_holder.h" #include "mojo/public/cpp/bindings/binding.h" namespace arc { +class ArcBridgeService; + // This class handles OBB mount/unmount requests from Android. class ArcObbMounterBridge : public ArcService,
diff --git a/components/arc/power/arc_power_bridge.cc b/components/arc/power/arc_power_bridge.cc index abec9d7..c49d0b5 100644 --- a/components/arc/power/arc_power_bridge.cc +++ b/components/arc/power/arc_power_bridge.cc
@@ -10,6 +10,7 @@ #include "ash/shell.h" #include "base/logging.h" #include "chromeos/dbus/power_policy_controller.h" +#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service_manager.h" namespace arc {
diff --git a/components/arc/power/arc_power_bridge.h b/components/arc/power/arc_power_bridge.h index c82c380..5bcffff 100644 --- a/components/arc/power/arc_power_bridge.h +++ b/components/arc/power/arc_power_bridge.h
@@ -8,14 +8,16 @@ #include <map> #include "base/macros.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/common/power.mojom.h" #include "components/arc/instance_holder.h" #include "mojo/public/cpp/bindings/binding.h" #include "ui/display/chromeos/display_configurator.h" namespace arc { +class ArcBridgeService; + // ARC Power Client sets power management policy based on requests from // ARC instances. class ArcPowerBridge : public ArcService,
diff --git a/components/arc/storage_manager/arc_storage_manager.h b/components/arc/storage_manager/arc_storage_manager.h index 8ea47cc..e544b9b 100644 --- a/components/arc/storage_manager/arc_storage_manager.h +++ b/components/arc/storage_manager/arc_storage_manager.h
@@ -9,12 +9,13 @@ #include "base/callback.h" #include "base/macros.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" #include "components/arc/common/storage_manager.mojom.h" namespace arc { +class ArcBridgeService; + // This class represents as a simple proxy of StorageManager to Chrome OS. class ArcStorageManager : public ArcService { public: @@ -32,7 +33,7 @@ // Gets storage usage of all application's APK, data, and cache size. using GetApplicationsSizeCallback = - base::Callback<void(bool succeeded, arc::mojom::ApplicationsSizePtr)>; + base::Callback<void(bool succeeded, mojom::ApplicationsSizePtr)>; bool GetApplicationsSize(const GetApplicationsSizeCallback& callback); // Deletes all applications' cache files.
diff --git a/components/arc/test/fake_app_instance.h b/components/arc/test/fake_app_instance.h index 3dcb277..60b702b 100644 --- a/components/arc/test/fake_app_instance.h +++ b/components/arc/test/fake_app_instance.h
@@ -91,7 +91,7 @@ const mojo::String& intent_uri, const base::Optional<gfx::Rect>& dimension_on_screen) override; void RequestIcon(const mojo::String& icon_resource_id, - arc::mojom::ScaleFactor scale_factor, + mojom::ScaleFactor scale_factor, const RequestIconCallback& callback) override; void RemoveCachedIcon(const mojo::String& icon_resource_id) override; void CanHandleResolution(
diff --git a/components/arc/test/fake_arc_bridge_service.h b/components/arc/test/fake_arc_bridge_service.h index 1f02339..963836c 100644 --- a/components/arc/test/fake_arc_bridge_service.h +++ b/components/arc/test/fake_arc_bridge_service.h
@@ -18,7 +18,7 @@ FakeArcBridgeService(); ~FakeArcBridgeService() override; - // arc::ArcBridgeService + // ArcBridgeService void HandleStartup() override; void Shutdown() override;
diff --git a/components/arc/test/fake_policy_instance.cc b/components/arc/test/fake_policy_instance.cc index b70c14c2..bfc37e1f 100644 --- a/components/arc/test/fake_policy_instance.cc +++ b/components/arc/test/fake_policy_instance.cc
@@ -4,8 +4,8 @@ #include <utility> -#include "components/arc/test/fake_policy_instance.h" #include "base/run_loop.h" +#include "components/arc/test/fake_policy_instance.h" namespace arc {
diff --git a/components/arc/test/fake_policy_instance.h b/components/arc/test/fake_policy_instance.h index 587fd7b..4f89e4c 100644 --- a/components/arc/test/fake_policy_instance.h +++ b/components/arc/test/fake_policy_instance.h
@@ -5,9 +5,7 @@ #ifndef COMPONENTS_ARC_TEST_FAKE_POLICY_INSTANCE_H_ #define COMPONENTS_ARC_TEST_FAKE_POLICY_INSTANCE_H_ -#include "components/arc/arc_bridge_service.h" #include "components/arc/common/policy.mojom.h" -#include "components/arc/instance_holder.h" namespace arc {
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc index 31072e4..01f0901e9 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc
@@ -161,11 +161,10 @@ UMA_HISTOGRAM_COUNTS_100( "DataReductionProxy.SuccessfulRequestCompletionCounts", proxy_info.proxy_index); - UMA_HISTOGRAM_ENUMERATION( - "DataReductionProxy.ProxySchemeUsed", - ConvertNetProxySchemeToProxyScheme( - proxy_info.proxy_servers.at(proxy_info.proxy_index).scheme()), - PROXY_SCHEME_MAX); + UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.ProxySchemeUsed", + ConvertNetProxySchemeToProxyScheme( + proxy_info.proxy_servers[0].scheme()), + PROXY_SCHEME_MAX); if (request->load_flags() & net::LOAD_MAIN_FRAME_DEPRECATED) { UMA_HISTOGRAM_COUNTS_100( "DataReductionProxy.SuccessfulRequestCompletionCounts.MainFrame",
diff --git a/components/history/core/browser/history_backend.cc b/components/history/core/browser/history_backend.cc index 166921d3..50383ba 100644 --- a/components/history/core/browser/history_backend.cc +++ b/components/history/core/browser/history_backend.cc
@@ -17,7 +17,6 @@ #include "base/compiler_specific.h" #include "base/files/file_enumerator.h" #include "base/memory/ptr_util.h" -#include "base/message_loop/message_loop.h" #include "base/metrics/histogram_macros.h" #include "base/rand_util.h" #include "base/sequenced_task_runner.h" @@ -213,7 +212,6 @@ scheduled_kill_db_(false), expirer_(this, backend_client.get(), task_runner), recent_redirects_(kMaxRedirectCount), - backend_destroy_message_loop_(nullptr), segment_queried_(false), backend_client_(std::move(backend_client)), task_runner_(task_runner) {} @@ -230,9 +228,8 @@ if (!backend_destroy_task_.is_null()) { // Notify an interested party (typically a unit test) that we're done. - DCHECK(backend_destroy_message_loop_); - backend_destroy_message_loop_->task_runner()->PostTask( - FROM_HERE, backend_destroy_task_); + DCHECK(backend_destroy_task_runner_); + backend_destroy_task_runner_->PostTask(FROM_HERE, backend_destroy_task_); } #if defined(OS_ANDROID) @@ -257,11 +254,12 @@ base::Bind(&HistoryBackend::OnMemoryPressure, base::Unretained(this)))); } -void HistoryBackend::SetOnBackendDestroyTask(base::MessageLoop* message_loop, - const base::Closure& task) { +void HistoryBackend::SetOnBackendDestroyTask( + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + const base::Closure& task) { if (!backend_destroy_task_.is_null()) DLOG(WARNING) << "Setting more than one destroy task, overriding"; - backend_destroy_message_loop_ = message_loop; + backend_destroy_task_runner_ = std::move(task_runner); backend_destroy_task_ = task; }
diff --git a/components/history/core/browser/history_backend.h b/components/history/core/browser/history_backend.h index 0d044f7..130d9b7b 100644 --- a/components/history/core/browser/history_backend.h +++ b/components/history/core/browser/history_backend.h
@@ -41,7 +41,6 @@ struct ThumbnailScore; namespace base { -class MessageLoop; class SingleThreadTaskRunner; } @@ -457,8 +456,9 @@ // Sets the task to run and the message loop to run it on when this object // is destroyed. See HistoryService::SetOnBackendDestroyTask for a more // complete description. - void SetOnBackendDestroyTask(base::MessageLoop* message_loop, - const base::Closure& task); + void SetOnBackendDestroyTask( + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + const base::Closure& task); // Adds the given rows to the database if it doesn't exist. A visit will be // added for each given URL at the last visit time in the URLRow if the @@ -852,7 +852,7 @@ base::Time first_recorded_time_; // When set, this is the task that should be invoked on destruction. - base::MessageLoop* backend_destroy_message_loop_; + scoped_refptr<base::SingleThreadTaskRunner> backend_destroy_task_runner_; base::Closure backend_destroy_task_; // Tracks page transition types.
diff --git a/components/history/core/browser/history_service.cc b/components/history/core/browser/history_service.cc index 55ad3ec9..a4993ca 100644 --- a/components/history/core/browser/history_service.cc +++ b/components/history/core/browser/history_service.cc
@@ -329,8 +329,8 @@ DCHECK(thread_checker_.CalledOnValidThread()); ScheduleTask( PRIORITY_NORMAL, - base::Bind(&HistoryBackend::SetOnBackendDestroyTask, - history_backend_, base::MessageLoop::current(), task)); + base::Bind(&HistoryBackend::SetOnBackendDestroyTask, history_backend_, + base::ThreadTaskRunnerHandle::Get(), task)); } void HistoryService::TopHosts(size_t num_hosts,
diff --git a/components/metrics/proto/cast_logs.proto b/components/metrics/proto/cast_logs.proto index 987c4f5..3341c642 100644 --- a/components/metrics/proto/cast_logs.proto +++ b/components/metrics/proto/cast_logs.proto
@@ -121,7 +121,7 @@ repeated CastConnectionInfo cast_connection_info = 2; // Stores Cast-enabled device specific events with a various context data. - // Next tag: 12 + // Next tag: 13 message CastEventProto { // The name of the action, hashed by same logic used to hash user action // event and histogram. @@ -157,6 +157,10 @@ // For application events associated with an assistant session, identifies // the assistant conversation. optional string conversation_key = 11; + + // Request ID of V2 Application Protocol, identifies a pair of request + // and response. + optional fixed32 request_id = 12; } repeated CastEventProto cast_event = 3;
diff --git a/components/safe_browsing_db/v4_store.cc b/components/safe_browsing_db/v4_store.cc index 83f3b99..faf61ec 100644 --- a/components/safe_browsing_db/v4_store.cc +++ b/components/safe_browsing_db/v4_store.cc
@@ -219,6 +219,11 @@ ApplyUpdateResult result = ProcessUpdate(metric, hash_prefix_map_old, response); + if (result == APPLY_UPDATE_SUCCESS) { + Checksum checksum = response->checksum(); + response.reset(); + RecordStoreWriteResult(WriteToDisk(checksum)); + } return result; } @@ -227,7 +232,9 @@ std::unique_ptr<ListUpdateResponse> response) { ApplyUpdateResult result = ProcessFullUpdate(metric, response); if (result == APPLY_UPDATE_SUCCESS) { - RecordStoreWriteResult(WriteToDisk(std::move(response))); + Checksum checksum = response->checksum(); + response.reset(); + RecordStoreWriteResult(WriteToDisk(checksum)); } return result; } @@ -627,20 +634,24 @@ StoreReadResult V4Store::ReadFromDisk() { DCHECK(task_runner_->RunsTasksOnCurrentThread()); - TimeTicks before = TimeTicks::Now(); - std::string contents; - bool read_success = base::ReadFileToString(store_path_, &contents); - if (!read_success) { - return FILE_UNREADABLE_FAILURE; - } - - if (contents.empty()) { - return FILE_EMPTY_FAILURE; - } - V4StoreFileFormat file_format; - if (!file_format.ParseFromString(contents)) { - return PROTO_PARSING_FAILURE; + TimeTicks before = TimeTicks::Now(); + { + // A temporary scope to make sure that |contents| get destroyed as soon as + // we are doing using it. + std::string contents; + bool read_success = base::ReadFileToString(store_path_, &contents); + if (!read_success) { + return FILE_UNREADABLE_FAILURE; + } + + if (contents.empty()) { + return FILE_EMPTY_FAILURE; + } + + if (!file_format.ParseFromString(contents)) { + return PROTO_PARSING_FAILURE; + } } if (file_format.magic_number() != kFileMagic) { @@ -671,28 +682,27 @@ return READ_SUCCESS; } -StoreWriteResult V4Store::WriteToDisk( - std::unique_ptr<ListUpdateResponse> response) const { - // Do not write partial updates to the disk. - // After merging the updates, the ListUpdateResponse passed to this method - // should be a FULL_UPDATE. - if (!response->has_response_type() || - response->response_type() != ListUpdateResponse::FULL_UPDATE) { - DVLOG(1) << "Failure: response->has_response_type(): " - << response->has_response_type() - << " : response->response_type(): " << response->response_type(); - return INVALID_RESPONSE_TYPE_FAILURE; +StoreWriteResult V4Store::WriteToDisk(const Checksum& checksum) const { + V4StoreFileFormat file_format; + ListUpdateResponse* lur = file_format.mutable_list_update_response(); + *(lur->mutable_checksum()) = checksum; + lur->set_new_client_state(state_); + lur->set_response_type(ListUpdateResponse::FULL_UPDATE); + for (auto map_iter : hash_prefix_map_) { + ThreatEntrySet* additions = lur->add_additions(); + // TODO(vakh): Write RICE encoded hash prefixes on disk. Not doing so + // currently since it takes a long time to decode them on startup, which + // blocks resource load. See: http://crbug.com/654819 + additions->set_compression_type(RAW); + additions->mutable_raw_hashes()->set_prefix_size(map_iter.first); + additions->mutable_raw_hashes()->set_raw_hashes(map_iter.second); } // Attempt writing to a temporary file first and at the end, swap the files. const base::FilePath new_filename = TemporaryFileForFilename(store_path_); - V4StoreFileFormat file_format; file_format.set_magic_number(kFileMagic); file_format.set_version_number(kFileVersion); - ListUpdateResponse* response_to_write = - file_format.mutable_list_update_response(); - response_to_write->Swap(response.get()); std::string file_format_string; file_format.SerializeToString(&file_format_string); size_t written = base::WriteFile(new_filename, file_format_string.data(),
diff --git a/components/safe_browsing_db/v4_store.h b/components/safe_browsing_db/v4_store.h index 3c6ea9d0..befa6f9b 100644 --- a/components/safe_browsing_db/v4_store.h +++ b/components/safe_browsing_db/v4_store.h
@@ -255,6 +255,7 @@ FRIEND_TEST_ALL_PREFIXES(V4StoreTest, TestRemovalsWithRiceEncodingSucceeds); FRIEND_TEST_ALL_PREFIXES(V4StoreTest, TestMergeUpdatesFailsChecksum); FRIEND_TEST_ALL_PREFIXES(V4StoreTest, TestChecksumErrorOnStartup); + FRIEND_TEST_ALL_PREFIXES(V4StoreTest, WriteToDiskFails); friend class V4StoreTest; // If |prefix_size| is within expected range, and |raw_hashes_length| is a @@ -361,9 +362,9 @@ const ::google::protobuf::RepeatedPtrField<ThreatEntrySet>& additions, HashPrefixMap* additions_map); - // Writes the FULL_UPDATE |response| to disk as a V4StoreFileFormat proto. - StoreWriteResult WriteToDisk( - std::unique_ptr<ListUpdateResponse> response) const; + // Writes the hash_prefix_map_ to disk as a V4StoreFileFormat proto. + // |checksum| is used to set the |checksum| field in the final proto. + StoreWriteResult WriteToDisk(const Checksum& checksum) const; // The checksum value as read from the disk, until it is verified. Once // verified, it is cleared.
diff --git a/components/safe_browsing_db/v4_store_unittest.cc b/components/safe_browsing_db/v4_store_unittest.cc index c3824c8..71b3e6f 100644 --- a/components/safe_browsing_db/v4_store_unittest.cc +++ b/components/safe_browsing_db/v4_store_unittest.cc
@@ -126,36 +126,9 @@ list_update_response.set_platform_type(LINUX_PLATFORM); list_update_response.set_response_type(ListUpdateResponse::FULL_UPDATE); WriteFileFormatProtoToFile(0x600D71FE, 9, &list_update_response); - EXPECT_EQ(READ_SUCCESS, V4Store(task_runner_, store_path_).ReadFromDisk()); -} - -TEST_F(V4StoreTest, TestWriteNoResponseType) { - EXPECT_EQ(INVALID_RESPONSE_TYPE_FAILURE, - V4Store(task_runner_, store_path_) - .WriteToDisk(base::WrapUnique(new ListUpdateResponse))); -} - -TEST_F(V4StoreTest, TestWritePartialResponseType) { - std::unique_ptr<ListUpdateResponse> list_update_response( - new ListUpdateResponse); - list_update_response->set_response_type(ListUpdateResponse::PARTIAL_UPDATE); - EXPECT_EQ(INVALID_RESPONSE_TYPE_FAILURE, - V4Store(task_runner_, store_path_) - .WriteToDisk(std::move(list_update_response))); -} - -TEST_F(V4StoreTest, TestWriteFullResponseType) { - std::unique_ptr<ListUpdateResponse> list_update_response( - new ListUpdateResponse); - list_update_response->set_response_type(ListUpdateResponse::FULL_UPDATE); - list_update_response->set_new_client_state("test_client_state"); - EXPECT_EQ(WRITE_SUCCESS, V4Store(task_runner_, store_path_) - .WriteToDisk(std::move(list_update_response))); - - V4Store read_store(task_runner_, store_path_); - EXPECT_EQ(READ_SUCCESS, read_store.ReadFromDisk()); - EXPECT_EQ("test_client_state", read_store.state_); - EXPECT_TRUE(read_store.hash_prefix_map_.empty()); + V4Store store(task_runner_, store_path_); + EXPECT_EQ(READ_SUCCESS, store.ReadFromDisk()); + EXPECT_TRUE(store.hash_prefix_map_.empty()); } TEST_F(V4StoreTest, TestAddUnlumpedHashesWithInvalidAddition) { @@ -569,22 +542,13 @@ } TEST_F(V4StoreTest, TestReadFullResponseWithValidHashPrefixMap) { - std::unique_ptr<ListUpdateResponse> lur(new ListUpdateResponse); - lur->set_response_type(ListUpdateResponse::FULL_UPDATE); - lur->set_new_client_state("test_client_state"); - lur->set_platform_type(WINDOWS_PLATFORM); - lur->set_threat_entry_type(URL); - lur->set_threat_type(MALWARE_THREAT); - ThreatEntrySet* additions = lur->add_additions(); - additions->set_compression_type(RAW); - additions->mutable_raw_hashes()->set_prefix_size(5); - additions->mutable_raw_hashes()->set_raw_hashes("00000abcde"); - additions = lur->add_additions(); - additions->set_compression_type(RAW); - additions->mutable_raw_hashes()->set_prefix_size(4); - additions->mutable_raw_hashes()->set_raw_hashes("00000abc"); - EXPECT_EQ(WRITE_SUCCESS, - V4Store(task_runner_, store_path_).WriteToDisk(std::move(lur))); + V4Store write_store(task_runner_, store_path_); + write_store.hash_prefix_map_[4] = "00000abc"; + write_store.hash_prefix_map_[5] = "00000abcde"; + write_store.state_ = "test_client_state"; + EXPECT_FALSE(base::PathExists(write_store.store_path_)); + EXPECT_EQ(WRITE_SUCCESS, write_store.WriteToDisk(Checksum())); + EXPECT_TRUE(base::PathExists(write_store.store_path_)); V4Store read_store (task_runner_, store_path_); EXPECT_EQ(READ_SUCCESS, read_store.ReadFromDisk()); @@ -599,18 +563,12 @@ // size is 5 so the parser isn't able to split the hash prefixes list // completely. TEST_F(V4StoreTest, TestReadFullResponseWithInvalidHashPrefixMap) { - std::unique_ptr<ListUpdateResponse> lur(new ListUpdateResponse); - lur->set_response_type(ListUpdateResponse::FULL_UPDATE); - lur->set_new_client_state("test_client_state"); - lur->set_platform_type(WINDOWS_PLATFORM); - lur->set_threat_entry_type(URL); - lur->set_threat_type(MALWARE_THREAT); - ThreatEntrySet* additions = lur->add_additions(); - additions->set_compression_type(RAW); - additions->mutable_raw_hashes()->set_prefix_size(5); - additions->mutable_raw_hashes()->set_raw_hashes("abcdef"); - EXPECT_EQ(WRITE_SUCCESS, - V4Store(task_runner_, store_path_).WriteToDisk(std::move(lur))); + V4Store write_store(task_runner_, store_path_); + write_store.hash_prefix_map_[5] = "abcdef"; + write_store.state_ = "test_client_state"; + EXPECT_FALSE(base::PathExists(write_store.store_path_)); + EXPECT_EQ(WRITE_SUCCESS, write_store.WriteToDisk(Checksum())); + EXPECT_TRUE(base::PathExists(write_store.store_path_)); V4Store read_store(task_runner_, store_path_); EXPECT_EQ(HASH_PREFIX_MAP_GENERATION_FAILURE, read_store.ReadFromDisk()); @@ -778,7 +736,10 @@ UpdatedStoreReadyCallback store_ready_callback = base::Bind(&V4StoreTest::UpdatedStoreReadyAfterRiceRemovals, base::Unretained(this), &called_back); + EXPECT_FALSE(base::PathExists(store.store_path_)); store.ApplyUpdate(std::move(lur), task_runner_, store_ready_callback); + EXPECT_TRUE(base::PathExists(store.store_path_)); + task_runner_->RunPendingTasks(); base::RunLoop().RunUntilIdle(); @@ -814,7 +775,6 @@ WriteFileFormatProtoToFile(0x600D71FE, 9, &list_update_response); V4Store store(task_runner_, store_path_); EXPECT_TRUE(store.expected_checksum_.empty()); - EXPECT_EQ(READ_SUCCESS, store.ReadFromDisk()); EXPECT_TRUE(!store.expected_checksum_.empty()); EXPECT_EQ("test_client_state", store.state()); @@ -849,4 +809,11 @@ EXPECT_TRUE(another_store.VerifyChecksum()); } +TEST_F(V4StoreTest, WriteToDiskFails) { + // Pass the directory name as file name so that when the code tries to rename + // the temp store file to |store_path_| it fails. + EXPECT_EQ(UNABLE_TO_RENAME_FAILURE, + V4Store(task_runner_, temp_dir_.GetPath()).WriteToDisk(Checksum())); +} + } // namespace safe_browsing
diff --git a/components/sessions/content/content_serialized_navigation_builder_unittest.cc b/components/sessions/content/content_serialized_navigation_builder_unittest.cc index 5f4029824..bdecc17 100644 --- a/components/sessions/content/content_serialized_navigation_builder_unittest.cc +++ b/components/sessions/content/content_serialized_navigation_builder_unittest.cc
@@ -87,20 +87,39 @@ base::ASCIIToUTF16(kExtendedInfoValue1)); entry->SetExtraData(kExtendedInfoKey2, base::ASCIIToUTF16(kExtendedInfoValue2)); - ContentSerializedNavigationDriver::GetInstance()->RegisterExtendedInfoHandler( - kExtendedInfoKey1, base::WrapUnique<ExtendedInfoHandler>( - new TestExtendedInfoHandler(kExtendedInfoKey1))); - ContentSerializedNavigationDriver::GetInstance()->RegisterExtendedInfoHandler( - kExtendedInfoKey2, base::WrapUnique<ExtendedInfoHandler>( - new TestExtendedInfoHandler(kExtendedInfoKey2))); } } // namespace +class ContentSerializedNavigationBuilderTest : public testing::Test { + public: + ContentSerializedNavigationBuilderTest() {} + ~ContentSerializedNavigationBuilderTest() override {} + + void SetUp() override { + ContentSerializedNavigationDriver* driver = + ContentSerializedNavigationDriver::GetInstance(); + driver->RegisterExtendedInfoHandler( + kExtendedInfoKey1, base::WrapUnique<ExtendedInfoHandler>( + new TestExtendedInfoHandler(kExtendedInfoKey1))); + driver->RegisterExtendedInfoHandler( + kExtendedInfoKey2, base::WrapUnique<ExtendedInfoHandler>( + new TestExtendedInfoHandler(kExtendedInfoKey2))); + } + + void TearDown() override { + ContentSerializedNavigationDriver* driver = + ContentSerializedNavigationDriver::GetInstance(); + driver->extended_info_handler_map_.clear(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ContentSerializedNavigationBuilderTest); +}; // Create a SerializedNavigationEntry from a NavigationEntry. All its fields // should match the NavigationEntry's. -TEST(ContentSerializedNavigationBuilderTest, FromNavigationEntry) { +TEST_F(ContentSerializedNavigationBuilderTest, FromNavigationEntry) { const std::unique_ptr<content::NavigationEntry> navigation_entry( MakeNavigationEntryForTest()); SetExtendedInfoForTest(navigation_entry.get()); @@ -146,7 +165,7 @@ // a SerializedNavigationEntry and back. The new one should match the old one // except for fields that aren't preserved, which should be set to // expected values. -TEST(ContentSerializedNavigationBuilderTest, ToNavigationEntry) { +TEST_F(ContentSerializedNavigationBuilderTest, ToNavigationEntry) { const std::unique_ptr<content::NavigationEntry> old_navigation_entry( MakeNavigationEntryForTest()); SetExtendedInfoForTest(old_navigation_entry.get()); @@ -197,7 +216,7 @@ EXPECT_EQ(kExtendedInfoValue2, base::UTF16ToASCII(extra_data)); } -TEST(ContentSerializedNavigationBuilderTest, SetPasswordState) { +TEST_F(ContentSerializedNavigationBuilderTest, SetPasswordState) { std::unique_ptr<content::NavigationEntry> entry( content::NavigationEntry::Create());
diff --git a/components/sessions/content/content_serialized_navigation_driver.h b/components/sessions/content/content_serialized_navigation_driver.h index a471738..768300d 100644 --- a/components/sessions/content/content_serialized_navigation_driver.h +++ b/components/sessions/content/content_serialized_navigation_driver.h
@@ -59,8 +59,10 @@ const ExtendedInfoHandlerMap& GetAllExtendedInfoHandlers() const; private: - ContentSerializedNavigationDriver(); friend struct base::DefaultSingletonTraits<ContentSerializedNavigationDriver>; + friend class ContentSerializedNavigationBuilderTest; + + ContentSerializedNavigationDriver(); ExtendedInfoHandlerMap extended_info_handler_map_;
diff --git a/components/sync/device_info/device_info_service.cc b/components/sync/device_info/device_info_service.cc index c331720..d6d327dd 100644 --- a/components/sync/device_info/device_info_service.cc +++ b/components/sync/device_info/device_info_service.cc
@@ -67,8 +67,7 @@ std::unique_ptr<MetadataChangeList> metadata_change_list, EntityDataMap entity_data_map) { DCHECK(has_provider_initialized_); - DCHECK(has_metadata_loaded_); - DCHECK(change_processor()); + DCHECK(change_processor()->IsTrackingMetadata()); // Local data should typically be near empty, with the only possible value // corresponding to this device. This is because on signout all device info @@ -122,7 +121,6 @@ std::unique_ptr<MetadataChangeList> metadata_change_list, EntityChangeList entity_changes) { DCHECK(has_provider_initialized_); - DCHECK(has_metadata_loaded_); std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch(); bool has_changes = false; @@ -153,8 +151,6 @@ void DeviceInfoService::GetData(StorageKeyList storage_keys, DataCallback callback) { - DCHECK(has_metadata_loaded_); - std::unique_ptr<DataBatchImpl> batch(new DataBatchImpl()); for (const auto& key : storage_keys) { const auto& iter = all_data_.find(key); @@ -163,18 +159,14 @@ batch->Put(key, CopyToEntityData(*iter->second)); } } - callback.Run(SyncError(), std::move(batch)); } void DeviceInfoService::GetAllData(DataCallback callback) { - DCHECK(has_metadata_loaded_); - std::unique_ptr<DataBatchImpl> batch(new DataBatchImpl()); for (const auto& kv : all_data_) { batch->Put(kv.first, CopyToEntityData(*kv.second)); } - callback.Run(SyncError(), std::move(batch)); } @@ -188,20 +180,6 @@ return entity_data.specifics.device_info().cache_guid(); } -void DeviceInfoService::OnChangeProcessorSet() { - // We've recieved a new processor that needs metadata. If we're still in the - // process of loading data and/or metadata, then |has_metadata_loaded_| is - // false and we'll wait for those async reads to happen. If we've already - // loaded metadata and then subsequently we get a new processor, we must not - // have created the processor ourselves because we had no metadata. So there - // must not be any metadata on disk. - if (has_metadata_loaded_) { - change_processor()->OnMetadataLoaded(SyncError(), - base::MakeUnique<MetadataBatch>()); - ReconcileLocalAndStored(); - } -} - bool DeviceInfoService::IsSyncing() const { return !all_data_.empty(); } @@ -212,19 +190,16 @@ if (iter == all_data_.end()) { return std::unique_ptr<DeviceInfo>(); } - return CopyToModel(*iter->second); } std::vector<std::unique_ptr<DeviceInfo>> DeviceInfoService::GetAllDeviceInfo() const { std::vector<std::unique_ptr<DeviceInfo>> list; - for (ClientIdToSpecifics::const_iterator iter = all_data_.begin(); iter != all_data_.end(); ++iter) { list.push_back(CopyToModel(*iter->second)); } - return list; } @@ -354,8 +329,6 @@ Result result, std::unique_ptr<RecordList> metadata_records, const std::string& global_metadata) { - DCHECK(!has_metadata_loaded_); - if (result != Result::SUCCESS) { // Store has encountered some serious error. We should still be able to // continue as a read only service, since if we got this far we must have @@ -364,27 +337,6 @@ return; } - // If we have no metadata then we don't want to create a processor. The idea - // is that by not having a processor, the services will suffer less of a - // performance hit. This isn't terribly applicable for this model type, but - // we want this class to be as similar to other services as possible so follow - // the convention. - if (metadata_records->size() > 0 || !global_metadata.empty()) { - CreateChangeProcessor(); - } - - // Set this after OnChangeProcessorSet so that we can correctly avoid giving - // the processor empty metadata. We always want to set |has_metadata_loaded_| - // at this point so that we'll know to give a processor empty metadata if it - // is created later. - has_metadata_loaded_ = true; - - if (!change_processor()) { - // This means we haven't been told to start syncing and we don't have any - // local metadata. - return; - } - std::unique_ptr<MetadataBatch> batch(new MetadataBatch()); ModelTypeState state; if (state.ParseFromString(global_metadata)) { @@ -430,8 +382,7 @@ // bother trying to track this case and act intelligently because simply not // much of a benefit in doing so. DCHECK(has_provider_initialized_); - DCHECK(has_metadata_loaded_); - DCHECK(change_processor()); + const DeviceInfo* current_info = local_device_info_provider_->GetLocalDeviceInfo(); auto iter = all_data_.find(current_info->guid()); @@ -453,11 +404,6 @@ void DeviceInfoService::SendLocalData() { DCHECK(has_provider_initialized_); - // TODO(skym): Handle disconnecting and reconnecting, this will currently halt - // the pulse timer and never restart it. - if (!change_processor()) { - return; - } std::unique_ptr<DeviceInfoSpecifics> specifics = CopyToSpecifics(*local_device_info_provider_->GetLocalDeviceInfo()); @@ -465,8 +411,11 @@ std::unique_ptr<MetadataChangeList> metadata_change_list = CreateMetadataChangeList(); - change_processor()->Put(specifics->cache_guid(), CopyToEntityData(*specifics), - metadata_change_list.get()); + if (change_processor()->IsTrackingMetadata()) { + change_processor()->Put(specifics->cache_guid(), + CopyToEntityData(*specifics), + metadata_change_list.get()); + } std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch(); StoreSpecifics(std::move(specifics), batch.get()); @@ -500,13 +449,8 @@ } void DeviceInfoService::ReportStartupErrorToSync(const std::string& msg) { - DCHECK(!has_metadata_loaded_); + // TODO(skym): Shouldn't need to log this here, reporting should always log. LOG(WARNING) << msg; - - // Create a processor and give it the error in case sync tries to start. - if (!change_processor()) { - CreateChangeProcessor(); - } change_processor()->OnMetadataLoaded( change_processor()->CreateAndUploadError(FROM_HERE, msg), nullptr); }
diff --git a/components/sync/device_info/device_info_service.h b/components/sync/device_info/device_info_service.h index c491826..be7af008 100644 --- a/components/sync/device_info/device_info_service.h +++ b/components/sync/device_info/device_info_service.h
@@ -62,7 +62,6 @@ void GetAllData(DataCallback callback) override; std::string GetClientTag(const EntityData& entity_data) override; std::string GetStorageKey(const EntityData& entity_data) override; - void OnChangeProcessorSet() override; // DeviceInfoTracker implementation. bool IsSyncing() const override; @@ -167,8 +166,6 @@ bool has_provider_initialized_ = false; // If data has been loaded from the store. bool has_data_loaded_ = false; - // if |change_processor()| has been given metadata. - bool has_metadata_loaded_ = false; // Used to update our local device info once every pulse interval. base::OneShotTimer pulse_timer_;
diff --git a/components/sync/device_info/device_info_service_unittest.cc b/components/sync/device_info/device_info_service_unittest.cc index 907b2ca..aa069d3 100644 --- a/components/sync/device_info/device_info_service_unittest.cc +++ b/components/sync/device_info/device_info_service_unittest.cc
@@ -179,8 +179,9 @@ std::unique_ptr<ModelTypeChangeProcessor> CreateModelTypeChangeProcessor( ModelType type, ModelTypeService* service) { - processor_ = new RecordingModelTypeChangeProcessor(); - return base::WrapUnique(processor_); + auto processor = base::MakeUnique<RecordingModelTypeChangeProcessor>(); + processor_ = processor.get(); + return std::move(processor); } // Initialized the service based on the current local device and store. Can @@ -196,11 +197,6 @@ service_->AddObserver(this); } - void OnSyncStarting() { - service()->OnSyncStarting(base::MakeUnique<DataTypeErrorHandlerMock>(), - StartCallback()); - } - // Creates the service and runs any outstanding tasks. This will typically // cause all initialization callbacks between the sevice and store to fire. void InitializeAndPump() { @@ -208,14 +204,6 @@ base::RunLoop().RunUntilIdle(); } - // Creates the service, runs any outstanding tasks, and then indicates to the - // service that sync wants to start and forces the processor to be created. - void InitializeAndPumpAndStart() { - InitializeAndPump(); - OnSyncStarting(); - ASSERT_TRUE(processor_); - } - // Generates a specifics object with slightly differing values. Will generate // the same values on each run of a test because a simple counter is used to // vary field values. @@ -240,7 +228,7 @@ // Override to allow specific cache guids. DeviceInfoSpecifics GenerateTestSpecifics(const std::string& guid) { - DeviceInfoSpecifics specifics(GenerateTestSpecifics()); + DeviceInfoSpecifics specifics = GenerateTestSpecifics(); specifics.set_cache_guid(guid); return specifics; } @@ -321,54 +309,46 @@ TEST_F(DeviceInfoServiceTest, EmptyDataReconciliation) { InitializeAndPump(); - ASSERT_EQ(0u, service()->GetAllDeviceInfo().size()); - OnSyncStarting(); - DeviceInfoList all_device_info(service()->GetAllDeviceInfo()); - ASSERT_EQ(1u, all_device_info.size()); - ASSERT_TRUE( - local_device()->GetLocalDeviceInfo()->Equals(*all_device_info[0])); + DeviceInfoList devices = service()->GetAllDeviceInfo(); + ASSERT_EQ(1u, devices.size()); + ASSERT_TRUE(local_device()->GetLocalDeviceInfo()->Equals(*devices[0])); } TEST_F(DeviceInfoServiceTest, EmptyDataReconciliationSlowLoad) { InitializeService(); - OnSyncStarting(); ASSERT_EQ(0u, service()->GetAllDeviceInfo().size()); base::RunLoop().RunUntilIdle(); - DeviceInfoList all_device_info(service()->GetAllDeviceInfo()); - ASSERT_EQ(1u, all_device_info.size()); - ASSERT_TRUE( - local_device()->GetLocalDeviceInfo()->Equals(*all_device_info[0])); + DeviceInfoList devices = service()->GetAllDeviceInfo(); + ASSERT_EQ(1u, devices.size()); + ASSERT_TRUE(local_device()->GetLocalDeviceInfo()->Equals(*devices[0])); } TEST_F(DeviceInfoServiceTest, LocalProviderSubscription) { set_local_device(base::MakeUnique<LocalDeviceInfoProviderMock>()); - InitializeAndPumpAndStart(); + InitializeAndPump(); ASSERT_EQ(0u, service()->GetAllDeviceInfo().size()); local_device()->Initialize(CreateDeviceInfo()); base::RunLoop().RunUntilIdle(); - DeviceInfoList all_device_info(service()->GetAllDeviceInfo()); - ASSERT_EQ(1u, all_device_info.size()); - ASSERT_TRUE( - local_device()->GetLocalDeviceInfo()->Equals(*all_device_info[0])); + DeviceInfoList devices = service()->GetAllDeviceInfo(); + ASSERT_EQ(1u, devices.size()); + ASSERT_TRUE(local_device()->GetLocalDeviceInfo()->Equals(*devices[0])); } // Metadata shouldn't be loaded before the provider is initialized. TEST_F(DeviceInfoServiceTest, LocalProviderInitRace) { set_local_device(base::WrapUnique(new LocalDeviceInfoProviderMock())); InitializeAndPump(); - OnSyncStarting(); EXPECT_FALSE(processor()->metadata()); ASSERT_EQ(0u, service()->GetAllDeviceInfo().size()); local_device()->Initialize(CreateDeviceInfo()); base::RunLoop().RunUntilIdle(); - DeviceInfoList all_device_info(service()->GetAllDeviceInfo()); - ASSERT_EQ(1u, all_device_info.size()); - ASSERT_TRUE( - local_device()->GetLocalDeviceInfo()->Equals(*all_device_info[0])); + DeviceInfoList devices = service()->GetAllDeviceInfo(); + ASSERT_EQ(1u, devices.size()); + ASSERT_TRUE(local_device()->GetLocalDeviceInfo()->Equals(*devices[0])); EXPECT_TRUE(processor()->metadata()); } @@ -394,7 +374,7 @@ TEST_F(DeviceInfoServiceTest, TestWithLocalData) { std::unique_ptr<WriteBatch> batch = store()->CreateWriteBatch(); - DeviceInfoSpecifics specifics(GenerateTestSpecifics()); + DeviceInfoSpecifics specifics = GenerateTestSpecifics(); store()->WriteData(batch.get(), specifics.cache_guid(), specifics.SerializeAsString()); store()->CommitWriteBatch(std::move(batch), @@ -402,9 +382,7 @@ InitializeAndPump(); - DeviceInfoList all_device_info(service()->GetAllDeviceInfo()); - ASSERT_EQ(1u, all_device_info.size()); - AssertEqual(specifics, *all_device_info[0]); + ASSERT_EQ(2u, service()->GetAllDeviceInfo().size()); AssertEqual(specifics, *service()->GetDeviceInfo(specifics.cache_guid()).get()); } @@ -417,16 +395,15 @@ store()->CommitWriteBatch(std::move(batch), base::Bind(&AssertResultIsSuccess)); InitializeAndPump(); - DeviceInfoList all_device_info(service()->GetAllDeviceInfo()); - ASSERT_EQ(1u, all_device_info.size()); - ASSERT_TRUE( - local_device()->GetLocalDeviceInfo()->Equals(*all_device_info[0])); + DeviceInfoList devices = service()->GetAllDeviceInfo(); + ASSERT_EQ(1u, devices.size()); + ASSERT_TRUE(local_device()->GetLocalDeviceInfo()->Equals(*devices[0])); EXPECT_EQ(1u, processor()->put_map().size()); } TEST_F(DeviceInfoServiceTest, TestWithLocalDataAndMetadata) { std::unique_ptr<WriteBatch> batch = store()->CreateWriteBatch(); - DeviceInfoSpecifics specifics(GenerateTestSpecifics()); + DeviceInfoSpecifics specifics = GenerateTestSpecifics(); store()->WriteData(batch.get(), specifics.cache_guid(), specifics.SerializeAsString()); ModelTypeState state; @@ -437,8 +414,7 @@ InitializeAndPump(); - DeviceInfoList all_device_info(service()->GetAllDeviceInfo()); - ASSERT_EQ(2u, all_device_info.size()); + ASSERT_EQ(2u, service()->GetAllDeviceInfo().size()); AssertEqual(specifics, *service()->GetDeviceInfo(specifics.cache_guid()).get()); ASSERT_TRUE(processor()->metadata()); @@ -448,9 +424,9 @@ TEST_F(DeviceInfoServiceTest, GetData) { std::unique_ptr<WriteBatch> batch = store()->CreateWriteBatch(); - DeviceInfoSpecifics specifics1(GenerateTestSpecifics()); - DeviceInfoSpecifics specifics2(GenerateTestSpecifics()); - DeviceInfoSpecifics specifics3(GenerateTestSpecifics()); + DeviceInfoSpecifics specifics1 = GenerateTestSpecifics(); + DeviceInfoSpecifics specifics2 = GenerateTestSpecifics(); + DeviceInfoSpecifics specifics3 = GenerateTestSpecifics(); store()->WriteData(batch.get(), specifics1.cache_guid(), specifics1.SerializeAsString()); store()->WriteData(batch.get(), specifics2.cache_guid(), @@ -483,8 +459,8 @@ TEST_F(DeviceInfoServiceTest, GetAllData) { std::unique_ptr<WriteBatch> batch = store()->CreateWriteBatch(); - DeviceInfoSpecifics specifics1(GenerateTestSpecifics()); - DeviceInfoSpecifics specifics2(GenerateTestSpecifics()); + DeviceInfoSpecifics specifics1 = GenerateTestSpecifics(); + DeviceInfoSpecifics specifics2 = GenerateTestSpecifics(); const std::string& guid1 = specifics1.cache_guid(); const std::string& guid2 = specifics2.cache_guid(); store()->WriteData(batch.get(), specifics1.cache_guid(), @@ -508,14 +484,16 @@ TEST_F(DeviceInfoServiceTest, ApplySyncChangesEmpty) { InitializeAndPump(); + EXPECT_EQ(1, change_count()); const SyncError error = service()->ApplySyncChanges( service()->CreateMetadataChangeList(), EntityChangeList()); EXPECT_FALSE(error.IsSet()); - EXPECT_EQ(0, change_count()); + EXPECT_EQ(1, change_count()); } TEST_F(DeviceInfoServiceTest, ApplySyncChangesInMemory) { InitializeAndPump(); + EXPECT_EQ(1, change_count()); DeviceInfoSpecifics specifics = GenerateTestSpecifics(); EntityChangeList add_changes; @@ -528,7 +506,7 @@ service()->GetDeviceInfo(specifics.cache_guid()); ASSERT_TRUE(info); AssertEqual(specifics, *info.get()); - EXPECT_EQ(1, change_count()); + EXPECT_EQ(2, change_count()); EntityChangeList delete_changes; delete_changes.push_back(EntityChange::CreateDelete(specifics.cache_guid())); @@ -537,25 +515,26 @@ EXPECT_FALSE(error.IsSet()); EXPECT_FALSE(service()->GetDeviceInfo(specifics.cache_guid())); - EXPECT_EQ(2, change_count()); + EXPECT_EQ(3, change_count()); } TEST_F(DeviceInfoServiceTest, ApplySyncChangesStore) { InitializeAndPump(); + EXPECT_EQ(1, change_count()); DeviceInfoSpecifics specifics = GenerateTestSpecifics(); EntityChangeList data_changes; PushBackEntityChangeAdd(specifics, &data_changes); ModelTypeState state; state.set_encryption_key_name("ekn"); - std::unique_ptr<MetadataChangeList> metadata_changes( - service()->CreateMetadataChangeList()); + std::unique_ptr<MetadataChangeList> metadata_changes = + service()->CreateMetadataChangeList(); metadata_changes->UpdateModelTypeState(state); const SyncError error = service()->ApplySyncChanges(std::move(metadata_changes), data_changes); EXPECT_FALSE(error.IsSet()); - EXPECT_EQ(1, change_count()); + EXPECT_EQ(2, change_count()); RestartService(); @@ -570,7 +549,7 @@ } TEST_F(DeviceInfoServiceTest, ApplySyncChangesWithLocalGuid) { - InitializeAndPumpAndStart(); + InitializeAndPump(); // The point of this test is to try to apply remote changes that have the same // cache guid as the local device. The service should ignore these changes @@ -609,7 +588,7 @@ } TEST_F(DeviceInfoServiceTest, ApplyDeleteNonexistent) { - InitializeAndPumpAndStart(); + InitializeAndPump(); EXPECT_EQ(1, change_count()); EntityChangeList delete_changes; delete_changes.push_back(EntityChange::CreateDelete("guid")); @@ -620,7 +599,7 @@ } TEST_F(DeviceInfoServiceTest, MergeEmpty) { - InitializeAndPumpAndStart(); + InitializeAndPump(); EXPECT_EQ(1, change_count()); const SyncError error = service()->MergeSyncData( service()->CreateMetadataChangeList(), EntityDataMap()); @@ -632,14 +611,14 @@ TEST_F(DeviceInfoServiceTest, MergeWithData) { const std::string conflict_guid = "conflict_guid"; - const DeviceInfoSpecifics unique_local( - GenerateTestSpecifics("unique_local_guid")); - const DeviceInfoSpecifics conflict_local( - GenerateTestSpecifics(conflict_guid)); - const DeviceInfoSpecifics conflict_remote( - GenerateTestSpecifics(conflict_guid)); - const DeviceInfoSpecifics unique_remote( - GenerateTestSpecifics("unique_remote_guid")); + const DeviceInfoSpecifics unique_local = + GenerateTestSpecifics("unique_local_guid"); + const DeviceInfoSpecifics conflict_local = + GenerateTestSpecifics(conflict_guid); + const DeviceInfoSpecifics conflict_remote = + GenerateTestSpecifics(conflict_guid); + const DeviceInfoSpecifics unique_remote = + GenerateTestSpecifics("unique_remote_guid"); std::unique_ptr<WriteBatch> batch = store()->CreateWriteBatch(); store()->WriteData(batch.get(), unique_local.cache_guid(), @@ -649,7 +628,7 @@ store()->CommitWriteBatch(std::move(batch), base::Bind(&AssertResultIsSuccess)); - InitializeAndPumpAndStart(); + InitializeAndPump(); EXPECT_EQ(1, change_count()); EntityDataMap remote_input; @@ -690,8 +669,8 @@ TEST_F(DeviceInfoServiceTest, MergeLocalGuid) { const DeviceInfo* local_device_info = local_device()->GetLocalDeviceInfo(); - std::unique_ptr<DeviceInfoSpecifics> specifics( - CopyToSpecifics(*local_device_info)); + std::unique_ptr<DeviceInfoSpecifics> specifics = + CopyToSpecifics(*local_device_info); specifics->set_last_updated_timestamp(TimeToProtoTime(Time::Now())); const std::string guid = local_device_info->guid(); @@ -700,7 +679,7 @@ store()->CommitWriteBatch(std::move(batch), base::Bind(&AssertResultIsSuccess)); - InitializeAndPumpAndStart(); + InitializeAndPump(); EntityDataMap remote_input; remote_input[guid] = SpecificsToEntity(*specifics); @@ -717,8 +696,8 @@ TEST_F(DeviceInfoServiceTest, GetLastUpdateTime) { Time time1(Time() + TimeDelta::FromDays(1)); - DeviceInfoSpecifics specifics1(GenerateTestSpecifics()); - DeviceInfoSpecifics specifics2(GenerateTestSpecifics()); + DeviceInfoSpecifics specifics1 = GenerateTestSpecifics(); + DeviceInfoSpecifics specifics2 = GenerateTestSpecifics(); specifics2.set_last_updated_timestamp(TimeToProtoTime(time1)); EXPECT_EQ(Time(), GetLastUpdateTime(specifics1)); @@ -727,7 +706,7 @@ TEST_F(DeviceInfoServiceTest, CountActiveDevices) { InitializeAndPump(); - EXPECT_EQ(0, service()->CountActiveDevices()); + EXPECT_EQ(1, service()->CountActiveDevices()); DeviceInfoSpecifics specifics = GenerateTestSpecifics(local_device()->GetLocalDeviceInfo()->guid()); @@ -735,21 +714,21 @@ PushBackEntityChangeAdd(specifics, &change_list); service()->ApplySyncChanges(service()->CreateMetadataChangeList(), change_list); - EXPECT_EQ(0, service()->CountActiveDevices()); + EXPECT_EQ(1, service()->CountActiveDevices()); change_list.clear(); specifics.set_last_updated_timestamp(TimeToProtoTime(Time::Now())); PushBackEntityChangeAdd(specifics, &change_list); service()->ApplySyncChanges(service()->CreateMetadataChangeList(), change_list); - EXPECT_EQ(0, service()->CountActiveDevices()); + EXPECT_EQ(1, service()->CountActiveDevices()); change_list.clear(); specifics.set_cache_guid("non-local"); PushBackEntityChangeAdd(specifics, &change_list); service()->ApplySyncChanges(service()->CreateMetadataChangeList(), change_list); - EXPECT_EQ(1, service()->CountActiveDevices()); + EXPECT_EQ(2, service()->CountActiveDevices()); } } // namespace
diff --git a/components/sync/driver/model_type_controller_unittest.cc b/components/sync/driver/model_type_controller_unittest.cc index 072d8fd..817168b 100644 --- a/components/sync/driver/model_type_controller_unittest.cc +++ b/components/sync/driver/model_type_controller_unittest.cc
@@ -186,19 +186,6 @@ } } - void ExpectHasChangeProcessor(bool has_processor) { - if (model_thread_.task_runner()->BelongsToCurrentThread()) { - DCHECK(service_); - EXPECT_EQ(has_processor, !!service_->change_processor()); - } else { - model_thread_.task_runner()->PostTask( - FROM_HERE, - base::Bind(&ModelTypeControllerTest::ExpectHasChangeProcessor, - base::Unretained(this), has_processor)); - PumpModelThread(); - } - } - SyncPrefs* sync_prefs() { return &sync_prefs_; } DataTypeController* controller() { return controller_.get(); } int load_models_done_count() { return load_models_done_count_; } @@ -330,10 +317,8 @@ controller()->Stop(); RunAllTasks(); EXPECT_EQ(DataTypeController::NOT_RUNNING, controller()->state()); - // Ensure that DisableSync is not called and service still has valid change - // processor. + // Ensure that DisableSync is not called. EXPECT_EQ(0, disable_sync_call_count()); - ExpectHasChangeProcessor(true); ExpectProcessorConnected(false); } @@ -354,10 +339,9 @@ controller()->Stop(); EXPECT_EQ(DataTypeController::NOT_RUNNING, controller()->state()); - // Ensure that DisableSync is called and change processor is reset. + // Ensure that DisableSync is called. PumpModelThread(); EXPECT_EQ(1, disable_sync_call_count()); - ExpectHasChangeProcessor(false); } // Test emulates disabling sync by signing out. DisableSync should be called. @@ -373,10 +357,9 @@ sync_prefs()->ClearPreferences(); controller()->Stop(); EXPECT_EQ(DataTypeController::NOT_RUNNING, controller()->state()); - // Ensure that DisableSync is called and change processor is reset. + // Ensure that DisableSync is called. PumpModelThread(); EXPECT_EQ(1, disable_sync_call_count()); - ExpectHasChangeProcessor(false); } // Test emulates disabling sync when datatype is not loaded yet. DisableSync @@ -393,8 +376,6 @@ EXPECT_EQ(DataTypeController::NOT_RUNNING, controller()->state()); // Ensure that DisableSync is not called. EXPECT_EQ(0, disable_sync_call_count()); - // A change processor was never created. - ExpectHasChangeProcessor(false); } } // namespace syncer
diff --git a/components/sync/model/fake_model_type_change_processor.cc b/components/sync/model/fake_model_type_change_processor.cc index d1f62f03..b4d3eacd 100644 --- a/components/sync/model/fake_model_type_change_processor.cc +++ b/components/sync/model/fake_model_type_change_processor.cc
@@ -45,6 +45,10 @@ void FakeModelTypeChangeProcessor::DisableSync() {} +bool FakeModelTypeChangeProcessor::IsTrackingMetadata() { + return true; +} + SyncError FakeModelTypeChangeProcessor::CreateAndUploadError( const tracked_objects::Location& location, const std::string& message) {
diff --git a/components/sync/model/fake_model_type_change_processor.h b/components/sync/model/fake_model_type_change_processor.h index 9efc284..4061a89 100644 --- a/components/sync/model/fake_model_type_change_processor.h +++ b/components/sync/model/fake_model_type_change_processor.h
@@ -37,6 +37,7 @@ void OnSyncStarting(std::unique_ptr<DataTypeErrorHandler> error_handler, const StartCallback& callback) override; void DisableSync() override; + bool IsTrackingMetadata() override; SyncError CreateAndUploadError(const tracked_objects::Location& location, const std::string& message) override; };
diff --git a/components/sync/model/fake_model_type_service.cc b/components/sync/model/fake_model_type_service.cc index 2ece834..f90b721 100644 --- a/components/sync/model/fake_model_type_service.cc +++ b/components/sync/model/fake_model_type_service.cc
@@ -137,7 +137,8 @@ FakeModelTypeService::FakeModelTypeService( const ChangeProcessorFactory& change_processor_factory) - : ModelTypeService(change_processor_factory, PREFERENCES) {} + : ModelTypeService(change_processor_factory, PREFERENCES), + db_(base::MakeUnique<Store>()) {} FakeModelTypeService::~FakeModelTypeService() { CheckPostConditions(); @@ -154,7 +155,7 @@ // Overloaded form to allow passing of custom entity data. void FakeModelTypeService::WriteItem(const std::string& key, std::unique_ptr<EntityData> entity_data) { - db_.PutData(key, *entity_data); + db_->PutData(key, *entity_data); if (change_processor()) { std::unique_ptr<MetadataChangeList> change_list( new SimpleMetadataChangeList()); @@ -164,7 +165,7 @@ } void FakeModelTypeService::DeleteItem(const std::string& key) { - db_.RemoveData(key); + db_->RemoveData(key); if (change_processor()) { std::unique_ptr<MetadataChangeList> change_list( new SimpleMetadataChangeList()); @@ -187,7 +188,7 @@ return error; } // Commit any local entities that aren't being overwritten by the server. - for (const auto& kv : db_.all_data()) { + for (const auto& kv : db_->all_data()) { if (data_map.find(kv.first) == data_map.end()) { change_processor()->Put(kv.first, CopyEntityData(*kv.second), metadata_changes.get()); @@ -195,7 +196,7 @@ } // Store any new remote entities. for (const auto& kv : data_map) { - db_.PutData(kv.first, kv.second.value()); + db_->PutData(kv.first, kv.second.value()); } ApplyMetadataChangeList(std::move(metadata_changes)); return SyncError(); @@ -212,16 +213,16 @@ for (const EntityChange& change : entity_changes) { switch (change.type()) { case EntityChange::ACTION_ADD: - EXPECT_FALSE(db_.HasData(change.storage_key())); - db_.PutData(change.storage_key(), change.data()); + EXPECT_FALSE(db_->HasData(change.storage_key())); + db_->PutData(change.storage_key(), change.data()); break; case EntityChange::ACTION_UPDATE: - EXPECT_TRUE(db_.HasData(change.storage_key())); - db_.PutData(change.storage_key(), change.data()); + EXPECT_TRUE(db_->HasData(change.storage_key())); + db_->PutData(change.storage_key(), change.data()); break; case EntityChange::ACTION_DELETE: - EXPECT_TRUE(db_.HasData(change.storage_key())); - db_.RemoveData(change.storage_key()); + EXPECT_TRUE(db_->HasData(change.storage_key())); + db_->RemoveData(change.storage_key()); break; } } @@ -238,11 +239,11 @@ for (const auto& kv : metadata_changes) { switch (kv.second.type) { case SimpleMetadataChangeList::UPDATE: - db_.PutMetadata(kv.first, kv.second.metadata); + db_->PutMetadata(kv.first, kv.second.metadata); break; case SimpleMetadataChangeList::CLEAR: - EXPECT_TRUE(db_.HasMetadata(kv.first)); - db_.RemoveMetadata(kv.first); + EXPECT_TRUE(db_->HasMetadata(kv.first)); + db_->RemoveMetadata(kv.first); break; } } @@ -251,10 +252,10 @@ changes->GetModelTypeStateChange(); switch (state_change.type) { case SimpleMetadataChangeList::UPDATE: - db_.set_model_type_state(state_change.state); + db_->set_model_type_state(state_change.state); break; case SimpleMetadataChangeList::CLEAR: - db_.set_model_type_state(ModelTypeState()); + db_->set_model_type_state(ModelTypeState()); break; } } @@ -268,8 +269,8 @@ } std::unique_ptr<DataBatchImpl> batch(new DataBatchImpl()); for (const std::string& key : keys) { - DCHECK(db_.HasData(key)) << "No data for " << key; - batch->Put(key, CopyEntityData(db_.GetData(key))); + DCHECK(db_->HasData(key)) << "No data for " << key; + batch->Put(key, CopyEntityData(db_->GetData(key))); } callback.Run(SyncError(), std::move(batch)); } @@ -281,7 +282,7 @@ return; } std::unique_ptr<DataBatchImpl> batch(new DataBatchImpl()); - for (const auto& kv : db_.all_data()) { + for (const auto& kv : db_->all_data()) { batch->Put(kv.first, CopyEntityData(*kv.second)); } callback.Run(SyncError(), std::move(batch)); @@ -295,13 +296,6 @@ return entity_data.specifics.preference().name(); } -void FakeModelTypeService::OnChangeProcessorSet() {} - -void FakeModelTypeService::SetServiceError(SyncError::ErrorType error_type) { - DCHECK(!service_error_.IsSet()); - service_error_ = SyncError(FROM_HERE, error_type, "TestError", PREFERENCES); -} - ConflictResolution FakeModelTypeService::ResolveConflict( const EntityData& local_data, const EntityData& remote_data) const { @@ -314,6 +308,11 @@ conflict_resolution_.reset(new ConflictResolution(std::move(resolution))); } +void FakeModelTypeService::SetServiceError(SyncError::ErrorType error_type) { + DCHECK(!service_error_.IsSet()); + service_error_ = SyncError(FROM_HERE, error_type, "TestError", PREFERENCES); +} + void FakeModelTypeService::CheckPostConditions() { DCHECK(!service_error_.IsSet()); }
diff --git a/components/sync/model/fake_model_type_service.h b/components/sync/model/fake_model_type_service.h index d607c73..3c9aa15b 100644 --- a/components/sync/model/fake_model_type_service.h +++ b/components/sync/model/fake_model_type_service.h
@@ -112,7 +112,6 @@ void GetAllData(DataCallback callback) override; std::string GetClientTag(const EntityData& entity_data) override; std::string GetStorageKey(const EntityData& entity_data) override; - void OnChangeProcessorSet() override; ConflictResolution ResolveConflict( const EntityData& local_data, const EntityData& remote_data) const override; @@ -124,14 +123,14 @@ // Sets the error that the next fallible call to the service will generate. void SetServiceError(SyncError::ErrorType error_type); - const Store& db() const { return db_; } + const Store& db() { return *db_; } protected: // Used to verify conditions upon destruction. virtual void CheckPostConditions(); // Contains all of the data and metadata state. - Store db_; + std::unique_ptr<Store> db_; private: // Applies |change_list| to the metadata store.
diff --git a/components/sync/model/model_type_change_processor.h b/components/sync/model/model_type_change_processor.h index 7fe4904..d1b2947 100644 --- a/components/sync/model/model_type_change_processor.h +++ b/components/sync/model/model_type_change_processor.h
@@ -66,6 +66,11 @@ // Indicates that sync is being disabled permanently for this data type. All // metadata should be erased from storage. virtual void DisableSync() = 0; + + // Returns a boolean representing whether the processor's metadata is + // currently up to date and accurately tracking the model type's data. If + // false, calls to Put and Delete will no-op and can be omitted by services. + virtual bool IsTrackingMetadata() = 0; }; } // namespace syncer
diff --git a/components/sync/model/model_type_service.cc b/components/sync/model/model_type_service.cc index 17905cc..59de0c9 100644 --- a/components/sync/model/model_type_service.cc +++ b/components/sync/model/model_type_service.cc
@@ -6,19 +6,23 @@ #include <utility> +#include "base/memory/ptr_util.h" +#include "components/sync/model/metadata_batch.h" + namespace syncer { ModelTypeService::ModelTypeService( const ChangeProcessorFactory& change_processor_factory, ModelType type) - : change_processor_factory_(change_processor_factory), type_(type) {} + : type_(type), + change_processor_factory_(change_processor_factory), + change_processor_(change_processor_factory_.Run(type_, this)) {} ModelTypeService::~ModelTypeService() {} ConflictResolution ModelTypeService::ResolveConflict( const EntityData& local_data, const EntityData& remote_data) const { - // TODO(maxbogue): Add tests once a file exists for them (crbug.com/543407). if (remote_data.is_deleted()) { DCHECK(!local_data.is_deleted()); return ConflictResolution::UseLocal(); @@ -29,30 +33,23 @@ void ModelTypeService::OnSyncStarting( std::unique_ptr<DataTypeErrorHandler> error_handler, const ModelTypeChangeProcessor::StartCallback& start_callback) { - CreateChangeProcessor(); change_processor_->OnSyncStarting(std::move(error_handler), start_callback); } void ModelTypeService::DisableSync() { DCHECK(change_processor_); change_processor_->DisableSync(); - change_processor_.reset(); -} - -void ModelTypeService::CreateChangeProcessor() { - if (!change_processor_) { - change_processor_ = change_processor_factory_.Run(type_, this); - DCHECK(change_processor_); - OnChangeProcessorSet(); - } + change_processor_ = change_processor_factory_.Run(type_, this); + // DisableSync() should delete all metadata, so it'll be safe to tell the new + // processor that there is no metadata. DisableSync() should never be called + // while the models are loading, aka before the service has finished loading + // the initial metadata. + change_processor_->OnMetadataLoaded(SyncError(), + base::MakeUnique<MetadataBatch>()); } ModelTypeChangeProcessor* ModelTypeService::change_processor() const { return change_processor_.get(); } -void ModelTypeService::clear_change_processor() { - change_processor_.reset(); -} - } // namespace syncer
diff --git a/components/sync/model/model_type_service.h b/components/sync/model/model_type_service.h index 1476e7e..62b7f9fc 100644 --- a/components/sync/model/model_type_service.h +++ b/components/sync/model/model_type_service.h
@@ -95,11 +95,6 @@ // should be. virtual std::string GetStorageKey(const EntityData& entity_data) = 0; - // Overridable notification for when the processor is set. This is typically - // when the service should start loading metadata and then subsequently giving - // it to the processor. - virtual void OnChangeProcessorSet() = 0; - // Resolve a conflict between the client and server versions of data. They are // guaranteed not to match (both be deleted or have identical specifics). A // default implementation chooses the server data unless it is a deletion. @@ -121,17 +116,12 @@ ModelTypeChangeProcessor* change_processor() const; - protected: - void CreateChangeProcessor(); - - void clear_change_processor(); - private: - std::unique_ptr<ModelTypeChangeProcessor> change_processor_; - - ChangeProcessorFactory change_processor_factory_; - const ModelType type_; + + const ChangeProcessorFactory change_processor_factory_; + + std::unique_ptr<ModelTypeChangeProcessor> change_processor_; }; } // namespace syncer
diff --git a/components/sync/model/model_type_service_unittest.cc b/components/sync/model/model_type_service_unittest.cc index 15db0d7..6dd7d88 100644 --- a/components/sync/model/model_type_service_unittest.cc +++ b/components/sync/model/model_type_service_unittest.cc
@@ -4,16 +4,21 @@ #include "components/sync/model/model_type_service.h" +#include <utility> + #include "base/bind.h" #include "base/memory/ptr_util.h" #include "components/sync/model/data_type_error_handler_mock.h" #include "components/sync/model/fake_model_type_change_processor.h" +#include "components/sync/model/metadata_batch.h" #include "components/sync/model/stub_model_type_service.h" +#include "components/sync/protocol/model_type_state.pb.h" #include "testing/gtest/include/gtest/gtest.h" namespace syncer { -// A mock MTCP that lets us know when DisableSync is called. +// A mock MTCP that lets verify DisableSync and OnMetadataLoaded were called in +// the ways that we expect. class MockModelTypeChangeProcessor : public FakeModelTypeChangeProcessor { public: explicit MockModelTypeChangeProcessor(const base::Closure& disabled_callback) @@ -22,8 +27,29 @@ void DisableSync() override { disabled_callback_.Run(); } + void OnMetadataLoaded(SyncError error, + std::unique_ptr<MetadataBatch> batch) override { + on_metadata_loaded_error_ = error; + on_metadata_loaded_batch_ = std::move(batch); + } + + const SyncError& on_metadata_loaded_error() const { + return on_metadata_loaded_error_; + } + MetadataBatch* on_metadata_loaded_batch() { + return on_metadata_loaded_batch_.get(); + } + private: + // This callback is invoked when DisableSync() is called, instead of + // remembering that this event happened in our own state. The reason for this + // is that after DisableSync() is called on us, the service is going to + // destroy this processor instance, and any state would be lost. The callback + // allows this information to reach somewhere safe instead. base::Closure disabled_callback_; + + SyncError on_metadata_loaded_error_; + std::unique_ptr<MetadataBatch> on_metadata_loaded_batch_; }; class MockModelTypeService : public StubModelTypeService { @@ -33,15 +59,11 @@ base::Unretained(this))) {} ~MockModelTypeService() override {} - void CreateChangeProcessor() { ModelTypeService::CreateChangeProcessor(); } - MockModelTypeChangeProcessor* change_processor() const { return static_cast<MockModelTypeChangeProcessor*>( ModelTypeService::change_processor()); } - bool on_processor_set_called() const { return on_processor_set_called_; } - void clear_on_processor_set_called() { on_processor_set_called_ = false; } bool processor_disable_sync_called() const { return processor_disable_sync_called_; } @@ -54,11 +76,8 @@ &MockModelTypeService::OnProcessorDisableSync, base::Unretained(this))); } - void OnChangeProcessorSet() override { on_processor_set_called_ = true; } - void OnProcessorDisableSync() { processor_disable_sync_called_ = true; } - bool on_processor_set_called_ = false; bool processor_disable_sync_called_ = false; }; @@ -84,32 +103,15 @@ start_callback_called_ = true; } - bool start_callback_called_; + bool start_callback_called_ = false; MockModelTypeService service_; }; -// CreateChangeProcessor should construct a processor and call -// OnChangeProcessorSet if and only if one doesn't already exist. -TEST_F(ModelTypeServiceTest, CreateChangeProcessor) { - EXPECT_FALSE(service()->change_processor()); - EXPECT_FALSE(service()->on_processor_set_called()); - service()->CreateChangeProcessor(); - ModelTypeChangeProcessor* processor = service()->change_processor(); - EXPECT_TRUE(processor); - EXPECT_TRUE(service()->on_processor_set_called()); - - // A second call shouldn't make a new processor. - service()->clear_on_processor_set_called(); - service()->CreateChangeProcessor(); - EXPECT_EQ(processor, service()->change_processor()); - EXPECT_FALSE(service()->on_processor_set_called()); -} - // OnSyncStarting should create a processor and call OnSyncStarting on it. TEST_F(ModelTypeServiceTest, OnSyncStarting) { - EXPECT_FALSE(service()->change_processor()); + EXPECT_FALSE(start_callback_called()); OnSyncStarting(); - EXPECT_TRUE(service()->change_processor()); + // FakeModelTypeProcessor is the one that calls the callback, so if it was // called then we know the call on the processor was made. EXPECT_TRUE(start_callback_called()); @@ -117,13 +119,21 @@ // DisableSync should call DisableSync on the processor and then delete it. TEST_F(ModelTypeServiceTest, DisableSync) { - service()->CreateChangeProcessor(); - EXPECT_TRUE(service()->change_processor()); EXPECT_FALSE(service()->processor_disable_sync_called()); - service()->DisableSync(); - EXPECT_FALSE(service()->change_processor()); + + // Disabling also wipes out metadata, and the service should have told the new + // processor about this. EXPECT_TRUE(service()->processor_disable_sync_called()); + + EXPECT_FALSE( + service()->change_processor()->on_metadata_loaded_error().IsSet()); + MetadataBatch* batch = + service()->change_processor()->on_metadata_loaded_batch(); + EXPECT_NE(nullptr, batch); + EXPECT_EQ(sync_pb::ModelTypeState().SerializeAsString(), + batch->GetModelTypeState().SerializeAsString()); + EXPECT_EQ(0U, batch->TakeAllMetadata().size()); } // ResolveConflicts should return USE_REMOTE unless the remote data is deleted.
diff --git a/components/sync/model/stub_model_type_service.cc b/components/sync/model/stub_model_type_service.cc index 266a0daf..591232f 100644 --- a/components/sync/model/stub_model_type_service.cc +++ b/components/sync/model/stub_model_type_service.cc
@@ -49,10 +49,4 @@ return std::string(); } -void StubModelTypeService::OnChangeProcessorSet() {} - -bool StubModelTypeService::HasChangeProcessor() const { - return change_processor() != nullptr; -} - } // namespace syncer
diff --git a/components/sync/model/stub_model_type_service.h b/components/sync/model/stub_model_type_service.h index f3461ba..2b04fd08 100644 --- a/components/sync/model/stub_model_type_service.h +++ b/components/sync/model/stub_model_type_service.h
@@ -32,9 +32,6 @@ void GetAllData(DataCallback callback) override; std::string GetClientTag(const EntityData& entity_data) override; std::string GetStorageKey(const EntityData& entity_data) override; - void OnChangeProcessorSet() override; - - bool HasChangeProcessor() const; }; } // namespace syncer
diff --git a/components/sync/model_impl/shared_model_type_processor.cc b/components/sync/model_impl/shared_model_type_processor.cc index 9aac047..06d0a1a9 100644 --- a/components/sync/model_impl/shared_model_type_processor.cc +++ b/components/sync/model_impl/shared_model_type_processor.cc
@@ -106,7 +106,7 @@ std::unique_ptr<ActivationContext> activation_context; if (!start_error_.IsSet()) { - activation_context = base::WrapUnique(new ActivationContext); + activation_context = base::MakeUnique<ActivationContext>(); activation_context->model_type_state = model_type_state_; activation_context->type_processor = base::MakeUnique<ModelTypeProcessorProxy>( @@ -129,6 +129,7 @@ void SharedModelTypeProcessor::DisableSync() { DCHECK(CalledOnValidThread()); + DCHECK(is_metadata_loaded_); std::unique_ptr<MetadataChangeList> change_list = service_->CreateMetadataChangeList(); for (auto it = entities_.begin(); it != entities_.end(); ++it) { @@ -139,6 +140,10 @@ service_->ApplySyncChanges(std::move(change_list), EntityChangeList()); } +bool SharedModelTypeProcessor::IsTrackingMetadata() { + return model_type_state_.initial_sync_done(); +} + SyncError SharedModelTypeProcessor::CreateAndUploadError( const tracked_objects::Location& location, const std::string& message) {
diff --git a/components/sync/model_impl/shared_model_type_processor.h b/components/sync/model_impl/shared_model_type_processor.h index 03887dc1..6b36e52 100644 --- a/components/sync/model_impl/shared_model_type_processor.h +++ b/components/sync/model_impl/shared_model_type_processor.h
@@ -58,6 +58,7 @@ void OnSyncStarting(std::unique_ptr<DataTypeErrorHandler> error_handler, const StartCallback& callback) override; void DisableSync() override; + bool IsTrackingMetadata() override; SyncError CreateAndUploadError(const tracked_objects::Location& location, const std::string& message) override;
diff --git a/components/sync/model_impl/shared_model_type_processor_unittest.cc b/components/sync/model_impl/shared_model_type_processor_unittest.cc index 75abb709..acef48e 100644 --- a/components/sync/model_impl/shared_model_type_processor_unittest.cc +++ b/components/sync/model_impl/shared_model_type_processor_unittest.cc
@@ -54,6 +54,79 @@ return SyncError(FROM_HERE, error_type, "TestError", PREFERENCES); } +EntitySpecifics GenerateSpecifics(const std::string& key, + const std::string& value) { + return FakeModelTypeService::GenerateSpecifics(key, value); +} + +std::unique_ptr<EntityData> GenerateEntityData(const std::string& key, + const std::string& value) { + return FakeModelTypeService::GenerateEntityData(key, value); +} + +class TestModelTypeService : public FakeModelTypeService { + public: + TestModelTypeService() + : FakeModelTypeService(base::Bind(&ModelTypeChangeProcessor::Create)) {} + + explicit TestModelTypeService(std::unique_ptr<TestModelTypeService> other) + : TestModelTypeService() { + std::swap(db_, other->db_); + } + + void OnPendingCommitDataLoaded() { + DCHECK(!data_callback_.is_null()); + data_callback_.Run(); + data_callback_.Reset(); + } + + void InitializeToReadyState() { + if (!data_callback_.is_null()) { + OnPendingCommitDataLoaded(); + } + } + + void SetInitialSyncDone(bool is_done) { + ModelTypeState model_type_state(db().model_type_state()); + model_type_state.set_initial_sync_done(is_done); + db_->set_model_type_state(model_type_state); + } + + int merge_call_count() const { return merge_call_count_; } + + // FakeModelTypeService overrides. + + SyncError MergeSyncData(std::unique_ptr<MetadataChangeList> mcl, + EntityDataMap entity_data_map) override { + merge_call_count_++; + return FakeModelTypeService::MergeSyncData(std::move(mcl), entity_data_map); + } + + void GetData(StorageKeyList keys, DataCallback callback) override { + FakeModelTypeService::GetData( + keys, base::Bind(&TestModelTypeService::CaptureDataCallback, + base::Unretained(this), callback)); + } + + void CheckPostConditions() override { + FakeModelTypeService::CheckPostConditions(); + DCHECK(data_callback_.is_null()); + } + + private: + void CaptureDataCallback(DataCallback callback, + SyncError error, + std::unique_ptr<DataBatch> data) { + data_callback_ = base::Bind(callback, error, base::Passed(std::move(data))); + } + + // The number of times MergeSyncData has been called. + int merge_call_count_ = 0; + + // Stores the data callback between GetData() and OnPendingCommitDataLoaded(). + base::Closure data_callback_; +}; + } // namespace // Tests the various functionality of SharedModelTypeProcessor. @@ -71,38 +144,30 @@ // storage and the correct commit requests on the worker side. // - Updates and commit responses from the worker correctly affect data and // metadata in storage on the service side. -class SharedModelTypeProcessorTest : public ::testing::Test, - public FakeModelTypeService { +class SharedModelTypeProcessorTest : public ::testing::Test { public: SharedModelTypeProcessorTest() - : FakeModelTypeService(base::Bind(&ModelTypeChangeProcessor::Create)) {} + : service_(base::MakeUnique<TestModelTypeService>()) {} + + ~SharedModelTypeProcessorTest() override { CheckPostConditions(); } void InitializeToMetadataLoaded() { - CreateChangeProcessor(); - ModelTypeState model_type_state(db_.model_type_state()); - model_type_state.set_initial_sync_done(true); - db_.set_model_type_state(model_type_state); + service()->SetInitialSyncDone(true); OnMetadataLoaded(); } // Initialize to a "ready-to-commit" state. void InitializeToReadyState() { InitializeToMetadataLoaded(); - if (!data_callback_.is_null()) { - OnPendingCommitDataLoaded(); - } + service()->InitializeToReadyState(); OnSyncStarting(); } void OnMetadataLoaded() { - type_processor()->OnMetadataLoaded(SyncError(), db_.CreateMetadataBatch()); + type_processor()->OnMetadataLoaded(SyncError(), db().CreateMetadataBatch()); } - void OnPendingCommitDataLoaded() { - DCHECK(!data_callback_.is_null()); - data_callback_.Run(); - data_callback_.Reset(); - } + void OnPendingCommitDataLoaded() { service()->OnPendingCommitDataLoaded(); } void OnSyncStarting() { std::unique_ptr<DataTypeErrorHandlerMock> error_handler = @@ -122,16 +187,17 @@ // Writes data for |key| and simulates a commit response for it. EntitySpecifics WriteItemAndAck(const std::string& key, const std::string& value) { - EntitySpecifics specifics = WriteItem(key, value); - worker()->ExpectPendingCommits({TagHashFromKey(key)}); + EntitySpecifics specifics = service()->WriteItem(key, value); + worker()->ExpectPendingCommits({FakeModelTypeService::TagHashFromKey(key)}); worker()->AckOnePendingCommit(); EXPECT_EQ(0U, worker()->GetNumPendingCommits()); return specifics; } - void ResetState() { - clear_change_processor(); - db_.Reset(); + void ResetState(bool keep_db) { + service_ = keep_db + ? base::MakeUnique<TestModelTypeService>(std::move(service_)) + : base::MakeUnique<TestModelTypeService>(); worker_ = nullptr; CheckPostConditions(); } @@ -139,33 +205,30 @@ // Wipes existing DB and simulates a pending update of a server-known item. EntitySpecifics ResetStateWriteItem(const std::string& name, const std::string& value) { - ResetState(); + ResetState(false); InitializeToReadyState(); EXPECT_EQ(0U, ProcessorEntityCount()); WriteItemAndAck(name, "acked-value"); - EntitySpecifics specifics = WriteItem(name, value); + EntitySpecifics specifics = service()->WriteItem(name, value); EXPECT_EQ(1U, ProcessorEntityCount()); - clear_change_processor(); - worker_ = nullptr; + ResetState(true); return specifics; } // Wipes existing DB and simulates a pending deletion of a server-known item. void ResetStateDeleteItem(const std::string& name, const std::string& value) { - ResetState(); + ResetState(false); InitializeToReadyState(); EXPECT_EQ(0U, ProcessorEntityCount()); WriteItemAndAck(name, value); EXPECT_EQ(1U, ProcessorEntityCount()); - DeleteItem(name); + service()->DeleteItem(name); EXPECT_EQ(1U, ProcessorEntityCount()); - clear_change_processor(); - worker_ = nullptr; + ResetState(true); } // Return the number of entities the processor has metadata for. size_t ProcessorEntityCount() const { - DCHECK(type_processor()); return type_processor()->entities_.size(); } @@ -176,23 +239,24 @@ expected_start_error_ = error_type; } - MockModelTypeWorker* worker() { return worker_; } + TestModelTypeService* service() const { return service_.get(); } + + const FakeModelTypeService::Store& db() const { return service()->db(); } + + MockModelTypeWorker* worker() const { return worker_; } SharedModelTypeProcessor* type_processor() const { - return static_cast<SharedModelTypeProcessor*>(change_processor()); + return static_cast<SharedModelTypeProcessor*>( + service()->change_processor()); } - DataTypeErrorHandlerMock* error_handler() { + DataTypeErrorHandlerMock* error_handler() const { DCHECK(error_handler_); return error_handler_; } - int merge_call_count() const { return merge_call_count_; } - private: - void CheckPostConditions() override { - FakeModelTypeService::CheckPostConditions(); - DCHECK(data_callback_.is_null()); + void CheckPostConditions() { DCHECK_EQ(SyncError::UNSET, expected_start_error_); } @@ -216,25 +280,7 @@ type_processor()->ConnectSync(std::move(worker)); } - // FakeModelTypeService overrides. - - SyncError MergeSyncData(std::unique_ptr<MetadataChangeList> mcl, - EntityDataMap entity_data_map) override { - merge_call_count_++; - return FakeModelTypeService::MergeSyncData(std::move(mcl), entity_data_map); - } - - void CaptureDataCallback(DataCallback callback, - SyncError error, - std::unique_ptr<DataBatch> data) { - data_callback_ = base::Bind(callback, error, base::Passed(std::move(data))); - } - - void GetData(StorageKeyList keys, DataCallback callback) override { - FakeModelTypeService::GetData( - keys, base::Bind(&SharedModelTypeProcessorTest::CaptureDataCallback, - base::Unretained(this), callback)); - } + std::unique_ptr<TestModelTypeService> service_; // This sets ThreadTaskRunnerHandle on the current thread, which the type // processor will pick up as the sync task runner. @@ -243,27 +289,20 @@ // The current mock queue, which is owned by |type_processor()|. MockModelTypeWorker* worker_; - // Stores the data callback between GetData() and OnPendingCommitDataLoaded(). - base::Closure data_callback_; - // The processor's error handler. DataTypeErrorHandlerMock* error_handler_; // The error to expect in OnReadyToConnect(). SyncError::ErrorType expected_start_error_ = SyncError::UNSET; - - // The number of times MergeSyncData has been called. - int merge_call_count_ = 0; }; // Test that an initial sync handles local and remote items properly. TEST_F(SharedModelTypeProcessorTest, InitialSync) { - CreateChangeProcessor(); OnMetadataLoaded(); OnSyncStarting(); // Local write before initial sync. - WriteItem(kKey1, kValue1); + service()->WriteItem(kKey1, kValue1); // Has data, but no metadata, entity in the processor, or commit request. EXPECT_EQ(1U, db().data_count()); @@ -271,10 +310,10 @@ EXPECT_EQ(0U, ProcessorEntityCount()); EXPECT_EQ(0U, worker()->GetNumPendingCommits()); - EXPECT_EQ(0, merge_call_count()); + EXPECT_EQ(0, service()->merge_call_count()); // Initial sync with one server item. worker()->UpdateFromServer(kHash2, GenerateSpecifics(kKey2, kValue2)); - EXPECT_EQ(1, merge_call_count()); + EXPECT_EQ(1, service()->merge_call_count()); // Now have data and metadata for both items, as well as a commit request for // the local item. @@ -292,40 +331,37 @@ InitializeToMetadataLoaded(); // Write an item before sync connects. - WriteItem(kKey1, kValue1); + service()->WriteItem(kKey1, kValue1); EXPECT_EQ(1U, db().data_count()); EXPECT_EQ(1U, db().metadata_count()); // Check that data coming from sync is treated as a normal GetUpdates. OnSyncStarting(); worker()->UpdateFromServer(kHash2, GenerateSpecifics(kKey2, kValue2)); - EXPECT_EQ(0, merge_call_count()); + EXPECT_EQ(0, service()->merge_call_count()); EXPECT_EQ(2U, db().data_count()); EXPECT_EQ(2U, db().metadata_count()); } // Test that an error during the merge is propagated to the error handler. TEST_F(SharedModelTypeProcessorTest, InitialSyncError) { - CreateChangeProcessor(); OnMetadataLoaded(); OnSyncStarting(); - SetServiceError(SyncError::DATATYPE_ERROR); + service()->SetServiceError(SyncError::DATATYPE_ERROR); error_handler()->ExpectError(SyncError::DATATYPE_ERROR); worker()->UpdateFromServer(); } // Test that errors before it's called are passed to |start_callback| correctly. TEST_F(SharedModelTypeProcessorTest, StartErrors) { - CreateChangeProcessor(); type_processor()->OnMetadataLoaded(CreateSyncError(SyncError::DATATYPE_ERROR), nullptr); ExpectStartError(SyncError::DATATYPE_ERROR); OnSyncStarting(); // Test OnSyncStarting happening first. - ResetState(); - CreateChangeProcessor(); + ResetState(false); OnSyncStarting(); ExpectStartError(SyncError::DATATYPE_ERROR); type_processor()->OnMetadataLoaded(CreateSyncError(SyncError::DATATYPE_ERROR), @@ -333,7 +369,7 @@ // Test an error loading pending data. ResetStateWriteItem(kKey1, kValue1); - SetServiceError(SyncError::DATATYPE_ERROR); + service()->SetServiceError(SyncError::DATATYPE_ERROR); InitializeToMetadataLoaded(); OnPendingCommitDataLoaded(); ExpectStartError(SyncError::DATATYPE_ERROR); @@ -373,7 +409,7 @@ InitializeToMetadataLoaded(); OnPendingCommitDataLoaded(); OnSyncStarting(); - EntitySpecifics specifics4 = WriteItem(kKey1, kValue2); + EntitySpecifics specifics4 = service()->WriteItem(kKey1, kValue2); EXPECT_EQ(2U, worker()->GetNumPendingCommits()); worker()->ExpectNthPendingCommit(0, kHash1, specifics3); worker()->ExpectNthPendingCommit(1, kHash1, specifics4); @@ -382,7 +418,7 @@ ResetStateWriteItem(kKey1, kValue1); InitializeToMetadataLoaded(); OnPendingCommitDataLoaded(); - EntitySpecifics specifics5 = WriteItem(kKey1, kValue2); + EntitySpecifics specifics5 = service()->WriteItem(kKey1, kValue2); OnSyncStarting(); EXPECT_EQ(1U, worker()->GetNumPendingCommits()); worker()->ExpectNthPendingCommit(0, kHash1, specifics5); @@ -392,7 +428,7 @@ InitializeToMetadataLoaded(); OnSyncStarting(); OnPendingCommitDataLoaded(); - EntitySpecifics specifics7 = WriteItem(kKey1, kValue2); + EntitySpecifics specifics7 = service()->WriteItem(kKey1, kValue2); EXPECT_EQ(2U, worker()->GetNumPendingCommits()); worker()->ExpectNthPendingCommit(0, kHash1, specifics6); worker()->ExpectNthPendingCommit(1, kHash1, specifics7); @@ -401,7 +437,7 @@ ResetStateWriteItem(kKey1, kValue1); InitializeToMetadataLoaded(); OnSyncStarting(); - EntitySpecifics specifics8 = WriteItem(kKey1, kValue2); + EntitySpecifics specifics8 = service()->WriteItem(kKey1, kValue2); EXPECT_EQ(nullptr, worker()); OnPendingCommitDataLoaded(); EXPECT_EQ(1U, worker()->GetNumPendingCommits()); @@ -410,7 +446,7 @@ // Put, data, connect. ResetStateWriteItem(kKey1, kValue1); InitializeToMetadataLoaded(); - EntitySpecifics specifics9 = WriteItem(kKey1, kValue2); + EntitySpecifics specifics9 = service()->WriteItem(kKey1, kValue2); OnPendingCommitDataLoaded(); OnSyncStarting(); EXPECT_EQ(1U, worker()->GetNumPendingCommits()); @@ -419,7 +455,7 @@ // Put, connect, data. ResetStateWriteItem(kKey1, kValue1); InitializeToMetadataLoaded(); - EntitySpecifics specifics10 = WriteItem(kKey1, kValue2); + EntitySpecifics specifics10 = service()->WriteItem(kKey1, kValue2); OnSyncStarting(); EXPECT_EQ(nullptr, worker()); OnPendingCommitDataLoaded(); @@ -431,7 +467,7 @@ InitializeToMetadataLoaded(); OnPendingCommitDataLoaded(); OnSyncStarting(); - DeleteItem(kKey1); + service()->DeleteItem(kKey1); EXPECT_EQ(2U, worker()->GetNumPendingCommits()); worker()->ExpectNthPendingCommit(0, kHash1, specifics11); worker()->ExpectNthPendingCommit(1, kHash1, kEmptySpecifics); @@ -440,7 +476,7 @@ ResetStateWriteItem(kKey1, kValue1); InitializeToMetadataLoaded(); OnPendingCommitDataLoaded(); - DeleteItem(kKey1); + service()->DeleteItem(kKey1); OnSyncStarting(); EXPECT_EQ(1U, worker()->GetNumPendingCommits()); worker()->ExpectNthPendingCommit(0, kHash1, kEmptySpecifics); @@ -450,7 +486,7 @@ InitializeToMetadataLoaded(); OnSyncStarting(); OnPendingCommitDataLoaded(); - DeleteItem(kKey1); + service()->DeleteItem(kKey1); EXPECT_EQ(2U, worker()->GetNumPendingCommits()); worker()->ExpectNthPendingCommit(0, kHash1, specifics12); worker()->ExpectNthPendingCommit(1, kHash1, kEmptySpecifics); @@ -459,7 +495,7 @@ ResetStateWriteItem(kKey1, kValue1); InitializeToMetadataLoaded(); OnSyncStarting(); - DeleteItem(kKey1); + service()->DeleteItem(kKey1); EXPECT_EQ(nullptr, worker()); OnPendingCommitDataLoaded(); EXPECT_EQ(1U, worker()->GetNumPendingCommits()); @@ -468,7 +504,7 @@ // Delete, data, connect. ResetStateWriteItem(kKey1, kValue1); InitializeToMetadataLoaded(); - DeleteItem(kKey1); + service()->DeleteItem(kKey1); OnPendingCommitDataLoaded(); OnSyncStarting(); EXPECT_EQ(1U, worker()->GetNumPendingCommits()); @@ -477,7 +513,7 @@ // Delete, connect, data. ResetStateWriteItem(kKey1, kValue1); InitializeToMetadataLoaded(); - DeleteItem(kKey1); + service()->DeleteItem(kKey1); OnSyncStarting(); EXPECT_EQ(nullptr, worker()); OnPendingCommitDataLoaded(); @@ -508,7 +544,7 @@ InitializeToMetadataLoaded(); OnSyncStarting(); EXPECT_EQ(1U, worker()->GetNumPendingCommits()); - EntitySpecifics specifics1 = WriteItem(kKey1, kValue2); + EntitySpecifics specifics1 = service()->WriteItem(kKey1, kValue2); EXPECT_EQ(2U, worker()->GetNumPendingCommits()); worker()->ExpectNthPendingCommit(0, kHash1, kEmptySpecifics); worker()->ExpectNthPendingCommit(1, kHash1, specifics1); @@ -516,7 +552,7 @@ // Put, connect. ResetStateDeleteItem(kKey1, kValue1); InitializeToMetadataLoaded(); - EntitySpecifics specifics2 = WriteItem(kKey1, kValue2); + EntitySpecifics specifics2 = service()->WriteItem(kKey1, kValue2); OnSyncStarting(); EXPECT_EQ(1U, worker()->GetNumPendingCommits()); worker()->ExpectNthPendingCommit(0, kHash1, specifics2); @@ -526,7 +562,7 @@ InitializeToMetadataLoaded(); OnSyncStarting(); EXPECT_EQ(1U, worker()->GetNumPendingCommits()); - DeleteItem(kKey1); + service()->DeleteItem(kKey1); EXPECT_EQ(2U, worker()->GetNumPendingCommits()); worker()->ExpectNthPendingCommit(0, kHash1, kEmptySpecifics); worker()->ExpectNthPendingCommit(1, kHash1, kEmptySpecifics); @@ -534,7 +570,7 @@ // Delete, connect. ResetStateDeleteItem(kKey1, kValue1); InitializeToMetadataLoaded(); - DeleteItem(kKey1); + service()->DeleteItem(kKey1); OnSyncStarting(); EXPECT_EQ(1U, worker()->GetNumPendingCommits()); worker()->ExpectNthPendingCommit(0, kHash1, kEmptySpecifics); @@ -544,7 +580,7 @@ TEST_F(SharedModelTypeProcessorTest, LoadCommited) { InitializeToReadyState(); WriteItemAndAck(kKey1, kValue1); - clear_change_processor(); + ResetState(true); // Test that a new processor loads the metadata without committing. InitializeToReadyState(); @@ -558,7 +594,7 @@ InitializeToReadyState(); EXPECT_EQ(0U, worker()->GetNumPendingCommits()); - WriteItem(kKey1, kValue1); + service()->WriteItem(kKey1, kValue1); // Verify the commit request this operation has triggered. worker()->ExpectPendingCommits({kHash1}); @@ -600,8 +636,8 @@ // propagated to the error handler. TEST_F(SharedModelTypeProcessorTest, ErrorApplyingAck) { InitializeToReadyState(); - WriteItem(kKey1, kValue1); - SetServiceError(SyncError::DATATYPE_ERROR); + service()->WriteItem(kKey1, kValue1); + service()->SetServiceError(SyncError::DATATYPE_ERROR); error_handler()->ExpectError(SyncError::DATATYPE_ERROR); worker()->AckOnePendingCommit(); } @@ -622,7 +658,7 @@ entity_data->non_unique_name = kKey1; entity_data->client_tag_hash = kHash3; entity_data->id = kId1; - WriteItem(kKey1, std::move(entity_data)); + service()->WriteItem(kKey1, std::move(entity_data)); EXPECT_EQ(1U, worker()->GetNumPendingCommits()); ASSERT_FALSE(worker()->HasPendingCommitForHash(kHash3)); @@ -647,7 +683,7 @@ entity_data->client_tag_hash = kHash3; // Make sure ID isn't overwritten either. entity_data->id = kId2; - WriteItem(kKey1, std::move(entity_data)); + service()->WriteItem(kKey1, std::move(entity_data)); EXPECT_EQ(2U, worker()->GetNumPendingCommits()); ASSERT_FALSE(worker()->HasPendingCommitForHash(kHash3)); @@ -672,7 +708,7 @@ TEST_F(SharedModelTypeProcessorTest, LocalUpdateItem) { InitializeToReadyState(); - WriteItem(kKey1, kValue1); + service()->WriteItem(kKey1, kValue1); EXPECT_EQ(1U, db().metadata_count()); worker()->ExpectPendingCommits({kHash1}); @@ -681,7 +717,7 @@ const EntityData& data_v1 = request_data_v1.entity.value(); const EntityMetadata metadata_v1 = db().GetMetadata(kKey1); - WriteItem(kKey1, kValue2); + service()->WriteItem(kKey1, kValue2); EXPECT_EQ(1U, db().metadata_count()); worker()->ExpectPendingCommits({kHash1, kHash1}); @@ -724,11 +760,11 @@ // commit request. TEST_F(SharedModelTypeProcessorTest, LocalUpdateItemRedundant) { InitializeToReadyState(); - WriteItem(kKey1, kValue1); + service()->WriteItem(kKey1, kValue1); EXPECT_EQ(1U, db().metadata_count()); worker()->ExpectPendingCommits({kHash1}); - WriteItem(kKey1, kValue1); + service()->WriteItem(kKey1, kValue1); worker()->ExpectPendingCommits({kHash1}); } @@ -766,7 +802,7 @@ // propagated to the error handler. TEST_F(SharedModelTypeProcessorTest, ErrorApplyingUpdate) { InitializeToReadyState(); - SetServiceError(SyncError::DATATYPE_ERROR); + service()->SetServiceError(SyncError::DATATYPE_ERROR); error_handler()->ExpectError(SyncError::DATATYPE_ERROR); worker()->UpdateFromServer(kHash1, GenerateSpecifics(kKey1, kValue1)); } @@ -804,7 +840,7 @@ EXPECT_EQ(1, metadata_v1.acked_sequence_number()); EXPECT_EQ(1, metadata_v1.server_version()); - DeleteItem(kKey1); + service()->DeleteItem(kKey1); EXPECT_EQ(0U, db().data_count()); // Metadata is not removed until the commit response comes back. EXPECT_EQ(1U, db().metadata_count()); @@ -827,7 +863,7 @@ // response, then getting the commit responses. TEST_F(SharedModelTypeProcessorTest, LocalDeleteItemInterleaved) { InitializeToReadyState(); - WriteItem(kKey1, kValue1); + service()->WriteItem(kKey1, kValue1); worker()->ExpectPendingCommits({kHash1}); const CommitRequestData& data_v1 = worker()->GetLatestPendingCommitForHash(kHash1); @@ -838,7 +874,7 @@ EXPECT_EQ(0, metadata_v1.acked_sequence_number()); EXPECT_EQ(kUncommittedVersion, metadata_v1.server_version()); - DeleteItem(kKey1); + service()->DeleteItem(kKey1); EXPECT_EQ(0U, db().data_count()); EXPECT_EQ(1U, db().metadata_count()); EXPECT_EQ(1U, ProcessorEntityCount()); @@ -895,7 +931,7 @@ // Should have no effect and not crash. TEST_F(SharedModelTypeProcessorTest, LocalDeleteUnknown) { InitializeToReadyState(); - DeleteItem(kKey1); + service()->DeleteItem(kKey1); EXPECT_EQ(0U, db().data_count()); EXPECT_EQ(0U, db().metadata_count()); EXPECT_EQ(0U, ProcessorEntityCount()); @@ -919,7 +955,7 @@ InitializeToReadyState(); EXPECT_EQ(0U, worker()->GetNumPendingCommits()); - WriteItem(kKey1, kValue1); + service()->WriteItem(kKey1, kValue1); EXPECT_EQ(1U, db().data_count()); EXPECT_EQ(1U, db().metadata_count()); const EntityMetadata metadata1 = db().GetMetadata(kKey1); @@ -927,7 +963,7 @@ // There should be one commit request for this item only. worker()->ExpectPendingCommits({kHash1}); - WriteItem(kKey2, kValue2); + service()->WriteItem(kKey2, kValue2); EXPECT_EQ(2U, db().data_count()); EXPECT_EQ(2U, db().metadata_count()); const EntityMetadata metadata2 = db().GetMetadata(kKey2); @@ -948,7 +984,7 @@ TEST_F(SharedModelTypeProcessorTest, ConflictResolutionChangesMatch) { InitializeToReadyState(); - EntitySpecifics specifics = WriteItem(kKey1, kValue1); + EntitySpecifics specifics = service()->WriteItem(kKey1, kValue1); EXPECT_EQ(1U, db().data_change_count()); EXPECT_EQ(kValue1, db().GetValue(kKey1)); EXPECT_EQ(1U, db().metadata_change_count()); @@ -967,8 +1003,8 @@ TEST_F(SharedModelTypeProcessorTest, ConflictResolutionUseLocal) { InitializeToReadyState(); - EntitySpecifics specifics = WriteItem(kKey1, kValue1); - SetConflictResolution(ConflictResolution::UseLocal()); + EntitySpecifics specifics = service()->WriteItem(kKey1, kValue1); + service()->SetConflictResolution(ConflictResolution::UseLocal()); worker()->UpdateFromServer(kHash1, GenerateSpecifics(kKey1, kValue2)); @@ -982,8 +1018,8 @@ TEST_F(SharedModelTypeProcessorTest, ConflictResolutionUseRemote) { InitializeToReadyState(); - WriteItem(kKey1, kValue1); - SetConflictResolution(ConflictResolution::UseRemote()); + service()->WriteItem(kKey1, kValue1); + service()->SetConflictResolution(ConflictResolution::UseRemote()); worker()->UpdateFromServer(kHash1, GenerateSpecifics(kKey1, kValue2)); // Updated client data and metadata; no new commit request. @@ -996,8 +1032,8 @@ TEST_F(SharedModelTypeProcessorTest, ConflictResolutionUseNew) { InitializeToReadyState(); - WriteItem(kKey1, kValue1); - SetConflictResolution( + service()->WriteItem(kKey1, kValue1); + service()->SetConflictResolution( ConflictResolution::UseNew(GenerateEntityData(kKey1, kValue3))); worker()->UpdateFromServer(kHash1, GenerateSpecifics(kKey1, kValue2)); @@ -1021,13 +1057,13 @@ WriteItemAndAck(kKey1, kValue1); // The second item has a commit request in progress. - WriteItem(kKey2, kValue2); + service()->WriteItem(kKey2, kValue2); EXPECT_TRUE(worker()->HasPendingCommitForHash(kHash2)); DisconnectSync(); // The third item is added after stopping. - WriteItem(kKey3, kValue3); + service()->WriteItem(kKey3, kValue3); // Reconnect. OnSyncStarting(); @@ -1056,19 +1092,19 @@ WriteItemAndAck(kKey1, kValue1); // The second item has a commit request in progress. - WriteItem(kKey2, kValue2); + service()->WriteItem(kKey2, kValue2); EXPECT_TRUE(worker()->HasPendingCommitForHash(kHash2)); - DisableSync(); + service()->DisableSync(); + EXPECT_FALSE(type_processor()->IsTrackingMetadata()); // The third item is added after disable. - WriteItem(kKey3, kValue3); + service()->WriteItem(kKey3, kValue3); // Now we re-enable. - CreateChangeProcessor(); - OnMetadataLoaded(); OnSyncStarting(); worker()->UpdateFromServer(); + EXPECT_TRUE(type_processor()->IsTrackingMetadata()); // Once we're ready to commit, all three local items should consider // themselves uncommitted and pending for commit. @@ -1082,7 +1118,7 @@ // Commit an item. EntitySpecifics specifics1 = WriteItemAndAck(kKey1, kValue1); // Create another item and don't wait for its commit response. - EntitySpecifics specifics2 = WriteItem(kKey2, kValue2); + EntitySpecifics specifics2 = service()->WriteItem(kKey2, kValue2); worker()->ExpectPendingCommits({kHash2}); EXPECT_EQ(1U, db().GetMetadata(kKey1).sequence_number()); EXPECT_EQ(1U, db().GetMetadata(kKey2).sequence_number()); @@ -1107,7 +1143,7 @@ TEST_F(SharedModelTypeProcessorTest, ReEncryptErrorLoadingData) { InitializeToReadyState(); WriteItemAndAck(kKey1, kValue1); - SetServiceError(SyncError::DATATYPE_ERROR); + service()->SetServiceError(SyncError::DATATYPE_ERROR); worker()->UpdateWithEncryptionKey("k1"); error_handler()->ExpectError(SyncError::DATATYPE_ERROR); OnPendingCommitDataLoaded(); @@ -1154,10 +1190,10 @@ TEST_F(SharedModelTypeProcessorTest, ReEncryptConflictResolutionUseLocal) { InitializeToReadyState(); worker()->UpdateWithEncryptionKey("k1"); - EntitySpecifics specifics = WriteItem(kKey1, kValue1); + EntitySpecifics specifics = service()->WriteItem(kKey1, kValue1); worker()->ExpectPendingCommits({kHash1}); - SetConflictResolution(ConflictResolution::UseLocal()); + service()->SetConflictResolution(ConflictResolution::UseLocal()); // Unencrypted update needs to be re-commited with key k1. worker()->UpdateFromServer(kHash1, GenerateSpecifics(kKey1, kValue2), 1, ""); @@ -1171,9 +1207,9 @@ TEST_F(SharedModelTypeProcessorTest, ReEncryptConflictResolutionUseRemote) { InitializeToReadyState(); worker()->UpdateWithEncryptionKey("k1"); - WriteItem(kKey1, kValue1); + service()->WriteItem(kKey1, kValue1); - SetConflictResolution(ConflictResolution::UseRemote()); + service()->SetConflictResolution(ConflictResolution::UseRemote()); // Unencrypted update needs to be re-commited with key k1. EntitySpecifics specifics = GenerateSpecifics(kKey1, kValue2); worker()->UpdateFromServer(kHash1, specifics, 1, ""); @@ -1188,9 +1224,9 @@ TEST_F(SharedModelTypeProcessorTest, ReEncryptConflictResolutionUseNew) { InitializeToReadyState(); worker()->UpdateWithEncryptionKey("k1"); - WriteItem(kKey1, kValue1); + service()->WriteItem(kKey1, kValue1); - SetConflictResolution( + service()->SetConflictResolution( ConflictResolution::UseNew(GenerateEntityData(kKey1, kValue3))); // Unencrypted update needs to be re-commited with key k1. worker()->UpdateFromServer(kHash1, GenerateSpecifics(kKey1, kValue2), 1, ""); @@ -1242,7 +1278,7 @@ InitializeToReadyState(); EntitySpecifics specifics1 = WriteItemAndAck(kKey1, kValue1); - EntitySpecifics specifics2 = WriteItem(kKey1, kValue2); + EntitySpecifics specifics2 = service()->WriteItem(kKey1, kValue2); UpdateResponseDataList update; update.push_back(worker()->GenerateUpdateData(kHash1, specifics1, 1, "k1")); worker()->UpdateWithEncryptionKey("k1", update); @@ -1254,8 +1290,8 @@ // Same as above but with two commit requests before one ack. TEST_F(SharedModelTypeProcessorTest, IgnoreRemoteEncryptionInterleaved) { InitializeToReadyState(); - EntitySpecifics specifics1 = WriteItem(kKey1, kValue1); - EntitySpecifics specifics2 = WriteItem(kKey1, kValue2); + EntitySpecifics specifics1 = service()->WriteItem(kKey1, kValue1); + EntitySpecifics specifics2 = service()->WriteItem(kKey1, kValue2); worker()->AckOnePendingCommit(); // kValue1 is now the base value. EXPECT_EQ(1U, worker()->GetNumPendingCommits());
diff --git a/components/webcrypto/algorithms/aes_kw.cc b/components/webcrypto/algorithms/aes_kw.cc index f64e1db..d1bf022 100644 --- a/components/webcrypto/algorithms/aes_kw.cc +++ b/components/webcrypto/algorithms/aes_kw.cc
@@ -2,18 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <openssl/aead.h> +#include <openssl/aes.h> #include <stddef.h> #include <stdint.h> #include <vector> -#include "base/logging.h" +#include "base/location.h" #include "base/memory/ptr_util.h" #include "base/numerics/safe_math.h" -#include "base/stl_util.h" #include "components/webcrypto/algorithms/aes.h" -#include "components/webcrypto/algorithms/util.h" #include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/crypto_data.h" #include "components/webcrypto/status.h" @@ -23,41 +21,6 @@ namespace { -const EVP_AEAD* GetAesKwAlgorithmFromKeySize(size_t key_size_bytes) { - switch (key_size_bytes) { - case 16: - return EVP_aead_aes_128_key_wrap(); - case 32: - return EVP_aead_aes_256_key_wrap(); - default: - return NULL; - } -} - -Status AesKwEncryptDecrypt(EncryptOrDecrypt mode, - const blink::WebCryptoAlgorithm& algorithm, - const blink::WebCryptoKey& key, - const CryptoData& data, - std::vector<uint8_t>* buffer) { - // These length checks are done in order to give a more specific error. These - // are not required for correctness. - if ((mode == ENCRYPT && data.byte_length() < 16) || - (mode == DECRYPT && data.byte_length() < 24)) { - return Status::ErrorDataTooSmall(); - } - if (data.byte_length() % 8) - return Status::ErrorInvalidAesKwDataLength(); - - const std::vector<uint8_t>& raw_key = GetSymmetricKeyData(key); - - return AeadEncryptDecrypt(mode, raw_key, data, - 8, // tag_length_bytes - CryptoData(), // iv - CryptoData(), // additional_data - GetAesKwAlgorithmFromKeySize(raw_key.size()), - buffer); -} - class AesKwImplementation : public AesAlgorithm { public: AesKwImplementation() @@ -69,14 +32,72 @@ const blink::WebCryptoKey& key, const CryptoData& data, std::vector<uint8_t>* buffer) const override { - return AesKwEncryptDecrypt(ENCRYPT, algorithm, key, data, buffer); + crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); + + // These length checks are done in order to give a more specific + // error. These are not required for correctness. + if (data.byte_length() < 16) + return Status::ErrorDataTooSmall(); + if (data.byte_length() % 8) + return Status::ErrorInvalidAesKwDataLength(); + + // Key import validates key sizes, so the bits computation will not + // overflow. + const std::vector<uint8_t>& raw_key = GetSymmetricKeyData(key); + AES_KEY aes_key; + if (AES_set_encrypt_key(raw_key.data(), + static_cast<unsigned>(raw_key.size() * 8), + &aes_key) < 0) { + return Status::OperationError(); + } + + // Key wrap's overhead is 8 bytes. + base::CheckedNumeric<size_t> length(data.byte_length()); + length += 8; + if (!length.IsValid()) + return Status::ErrorDataTooLarge(); + + buffer->resize(length.ValueOrDie()); + if (AES_wrap_key(&aes_key, nullptr /* default IV */, buffer->data(), + data.bytes(), data.byte_length()) < 0) { + return Status::OperationError(); + } + + return Status::Success(); } Status Decrypt(const blink::WebCryptoAlgorithm& algorithm, const blink::WebCryptoKey& key, const CryptoData& data, std::vector<uint8_t>* buffer) const override { - return AesKwEncryptDecrypt(DECRYPT, algorithm, key, data, buffer); + crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); + + // These length checks are done in order to give a more specific + // error. These are not required for correctness. + if (data.byte_length() < 24) + return Status::ErrorDataTooSmall(); + if (data.byte_length() % 8) + return Status::ErrorInvalidAesKwDataLength(); + + // Key import validates key sizes, so the bits computation will not + // overflow. + const std::vector<uint8_t>& raw_key = GetSymmetricKeyData(key); + AES_KEY aes_key; + if (AES_set_decrypt_key(raw_key.data(), + static_cast<unsigned>(raw_key.size() * 8), + &aes_key) < 0) { + return Status::OperationError(); + } + + // Key wrap's overhead is 8 bytes. + buffer->resize(data.byte_length() - 8); + + if (AES_unwrap_key(&aes_key, nullptr /* default IV */, buffer->data(), + data.bytes(), data.byte_length()) < 0) { + return Status::OperationError(); + } + + return Status::Success(); } };
diff --git a/content/browser/accessibility/accessibility_ui.cc b/content/browser/accessibility/accessibility_ui.cc index cf0db114..20f0417 100644 --- a/content/browser/accessibility/accessibility_ui.cc +++ b/content/browser/accessibility/accessibility_ui.cc
@@ -19,6 +19,7 @@ #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/browser/web_contents/web_contents_impl.h" +#include "content/browser/webui/web_ui_data_source_impl.h" #include "content/common/view_message_enums.h" #include "content/grit/content_resources.h" #include "content/public/browser/favicon_status.h" @@ -142,8 +143,8 @@ AccessibilityUI::AccessibilityUI(WebUI* web_ui) : WebUIController(web_ui) { // Set up the chrome://accessibility source. - WebUIDataSource* html_source = - WebUIDataSource::Create(kChromeUIAccessibilityHost); + WebUIDataSourceImpl* html_source = static_cast<WebUIDataSourceImpl*>( + WebUIDataSource::Create(kChromeUIAccessibilityHost)); web_ui->RegisterMessageCallback( "toggleAccessibility", @@ -170,6 +171,8 @@ html_source->SetRequestFilter( base::Bind(&HandleRequestCallback, web_ui->GetWebContents()->GetBrowserContext())); + html_source->DisableI18nAndUseGzipForAllPaths(); + html_source->ExcludePathFromGzip(kDataFile); BrowserContext* browser_context = web_ui->GetWebContents()->GetBrowserContext();
diff --git a/content/browser/frame_host/interstitial_page_impl.cc b/content/browser/frame_host/interstitial_page_impl.cc index 78650a3..b338d4ed 100644 --- a/content/browser/frame_host/interstitial_page_impl.cc +++ b/content/browser/frame_host/interstitial_page_impl.cc
@@ -381,7 +381,6 @@ void InterstitialPageImpl::UpdateTitle( RenderFrameHost* render_frame_host, - int32_t page_id, const base::string16& title, base::i18n::TextDirection title_direction) { if (!enabled())
diff --git a/content/browser/frame_host/interstitial_page_impl.h b/content/browser/frame_host/interstitial_page_impl.h index 9866b47..8117b32 100644 --- a/content/browser/frame_host/interstitial_page_impl.h +++ b/content/browser/frame_host/interstitial_page_impl.h
@@ -113,7 +113,6 @@ const IPC::Message& message) override; void RenderFrameCreated(RenderFrameHost* render_frame_host) override; void UpdateTitle(RenderFrameHost* render_frame_host, - int32_t page_id, const base::string16& title, base::i18n::TextDirection title_direction) override; InterstitialPage* GetAsInterstitialPage() override;
diff --git a/content/browser/frame_host/render_frame_host_delegate.h b/content/browser/frame_host/render_frame_host_delegate.h index b251094..9beea2a 100644 --- a/content/browser/frame_host/render_frame_host_delegate.h +++ b/content/browser/frame_host/render_frame_host_delegate.h
@@ -118,7 +118,6 @@ // The page's title was changed and should be updated. Only called for the // top-level frame. virtual void UpdateTitle(RenderFrameHost* render_frame_host, - int32_t page_id, const base::string16& title, base::i18n::TextDirection title_direction) {}
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index ac12b26..c9be36dc 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -94,9 +94,11 @@ #include "device/geolocation/geolocation_service_context.h" #include "device/vibration/vibration_manager_impl.h" #include "device/wake_lock/wake_lock_service_context.h" +#include "media/base/media_switches.h" #include "media/mojo/interfaces/media_service.mojom.h" #include "media/mojo/interfaces/service_factory.mojom.h" #include "mojo/public/cpp/bindings/associated_interface_ptr.h" +#include "mojo/public/cpp/bindings/strong_binding.h" #include "services/shell/public/cpp/connector.h" #include "services/shell/public/cpp/interface_provider.h" #include "ui/accessibility/ax_tree.h" @@ -110,6 +112,10 @@ #if defined(ENABLE_MOJO_CDM) #include "content/browser/media/android/provision_fetcher_impl.h" #endif +#include "content/browser/media/android/media_player_renderer.h" +#include "media/base/audio_renderer_sink.h" +#include "media/base/video_renderer_sink.h" +#include "media/mojo/services/mojo_renderer_service.h" //nogncheck #endif #if defined(OS_MACOSX) @@ -211,7 +217,26 @@ void RenderFrameHost::AllowInjectingJavaScriptForAndroidWebView() { g_allow_injecting_javascript = true; } -#endif + +void CreateMediaPlayerRenderer( + content::RenderFrameHost* render_frame_host, + mojo::InterfaceRequest<media::mojom::Renderer> request) { + std::unique_ptr<MediaPlayerRenderer> renderer = + base::MakeUnique<MediaPlayerRenderer>(render_frame_host); + + // base::Unretained is safe here because the lifetime of the MediaPlayerRender + // is tied to the lifetime of the MojoRendererService. + media::MojoRendererService::InitiateSurfaceRequestCB surface_request_cb = + base::Bind(&MediaPlayerRenderer::InitiateScopedSurfaceRequest, + base::Unretained(renderer.get())); + + media::MojoRendererService::Create( + nullptr, // CDMs are not supported. + nullptr, // Manages its own audio_sink. + nullptr, // Does not use video_sink. See StreamTextureWrapper instead. + std::move(renderer), surface_request_cb, std::move(request)); +} +#endif // defined(OS_ANDROID) // static RenderFrameHostImpl* RenderFrameHostImpl::FromID(int process_id, @@ -650,7 +675,6 @@ OnEnforceInsecureRequestPolicy) IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateToUniqueOrigin, OnUpdateToUniqueOrigin) - IPC_MESSAGE_HANDLER(FrameHostMsg_DidAssignPageId, OnDidAssignPageId) IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeSandboxFlags, OnDidChangeSandboxFlags) IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeFrameOwnerProperties, @@ -1729,12 +1753,6 @@ is_potentially_trustworthy_unique_origin); } -void RenderFrameHostImpl::OnDidAssignPageId(int32_t page_id) { - // Update the RVH's current page ID so that future IPCs from the renderer - // correspond to the new page. - render_view_host_->page_id_ = page_id; -} - FrameTreeNode* RenderFrameHostImpl::FindAndVerifyChild( int32_t child_frame_routing_id, bad_message::BadMessageReason reason) { @@ -1799,9 +1817,8 @@ return; } - delegate_->UpdateTitle(this, render_view_host_->page_id_, title, - WebTextDirectionToChromeTextDirection( - title_direction)); + delegate_->UpdateTitle( + this, title, WebTextDirectionToChromeTextDirection(title_direction)); } void RenderFrameHostImpl::OnUpdateEncoding(const std::string& encoding_name) { @@ -2188,10 +2205,16 @@ GetInterfaceRegistry()->AddInterface( GetGlobalJavaInterfaces() ->CreateInterfaceFactory<device::VibrationManager>()); + + if (base::FeatureList::IsEnabled(media::kAndroidMediaPlayerRenderer)) { + // Creates a MojoRendererService, passing it a MediaPlayerRender. + GetInterfaceRegistry()->AddInterface<media::mojom::Renderer>(base::Bind( + &content::CreateMediaPlayerRenderer, base::Unretained(this))); + } #else GetInterfaceRegistry()->AddInterface( base::Bind(&device::VibrationManagerImpl::Create)); -#endif +#endif // defined(OS_ANDROID) bool enable_web_bluetooth = base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableWebBluetooth);
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index d21b5e5..69aaa1a 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -683,7 +683,6 @@ void OnDidAddContentSecurityPolicy(const ContentSecurityPolicyHeader& header); void OnEnforceInsecureRequestPolicy(blink::WebInsecureRequestPolicy policy); void OnUpdateToUniqueOrigin(bool is_potentially_trustworthy_unique_origin); - void OnDidAssignPageId(int32_t page_id); void OnDidChangeSandboxFlags(int32_t frame_routing_id, blink::WebSandboxFlags flags); void OnDidChangeFrameOwnerProperties(int32_t frame_routing_id,
diff --git a/content/browser/media/android/media_player_renderer.cc b/content/browser/media/android/media_player_renderer.cc index 62ae9266..756b9a9 100644 --- a/content/browser/media/android/media_player_renderer.cc +++ b/content/browser/media/android/media_player_renderer.cc
@@ -81,6 +81,18 @@ media_player_->Start(); media_player_->SeekTo(time); + + // WMPI needs to receive a BUFFERING_HAVE_ENOUGH data before sending a + // playback_rate > 0. The MediaPlayer manages its own buffering and will pause + // internally if ever it runs out of data. Sending BUFFERING_HAVE_ENOUGH here + // is always safe. + // + // NOTE: OnBufferingUpdate is triggered whenever the media has buffered or + // played up to a % value between 1-100, and it's not a reliable indicator of + // the buffering state. + // + // TODO(tguilbert): Investigate the effect of this call on UMAs. + renderer_client_->OnBufferingStateChange(media::BUFFERING_HAVE_ENOUGH); } void MediaPlayerRenderer::SetPlaybackRate(double playback_rate) { @@ -182,15 +194,7 @@ void MediaPlayerRenderer::OnMediaInterrupted(int player_id) {} -void MediaPlayerRenderer::OnBufferingUpdate(int player_id, int percentage) { - // As per Android documentation, |percentage| actually indicates "percentage - // buffered or played". E.g. if we are at 50% playback and have 1% - // buffered, |percentage| will be equal to 51. - // - // MediaPlayer manages its own buffering and will pause internally if ever it - // runs out of data. Therefore, we can always return BUFFERING_HAVE_ENOUGH. - renderer_client_->OnBufferingStateChange(media::BUFFERING_HAVE_ENOUGH); -} +void MediaPlayerRenderer::OnBufferingUpdate(int player_id, int percentage) {} void MediaPlayerRenderer::OnSeekComplete(int player_id, const base::TimeDelta& current_time) {}
diff --git a/content/browser/media/capture/web_contents_audio_input_stream.cc b/content/browser/media/capture/web_contents_audio_input_stream.cc index 4a58cc3..348af60 100644 --- a/content/browser/media/capture/web_contents_audio_input_stream.cc +++ b/content/browser/media/capture/web_contents_audio_input_stream.cc
@@ -349,22 +349,19 @@ const std::string& device_id, const media::AudioParameters& params, const scoped_refptr<base::SingleThreadTaskRunner>& worker_task_runner, - AudioMirroringManager* audio_mirroring_manager, - bool is_duplication) { - int render_process_id; - int main_render_frame_id; - if (!WebContentsMediaCaptureId::ExtractTabCaptureTarget( - device_id, &render_process_id, &main_render_frame_id)) { + AudioMirroringManager* audio_mirroring_manager) { + WebContentsMediaCaptureId media_id; + if (!WebContentsMediaCaptureId::Parse(device_id, &media_id)) { return NULL; } return new WebContentsAudioInputStream( - render_process_id, main_render_frame_id, audio_mirroring_manager, - new WebContentsTracker(false), + media_id.render_process_id, media_id.main_render_frame_id, + audio_mirroring_manager, new WebContentsTracker(false), new media::VirtualAudioInputStream( params, worker_task_runner, media::VirtualAudioInputStream::AfterCloseCallback()), - is_duplication); + !media_id.disable_local_echo); } WebContentsAudioInputStream::WebContentsAudioInputStream(
diff --git a/content/browser/media/capture/web_contents_audio_input_stream.h b/content/browser/media/capture/web_contents_audio_input_stream.h index 1c44443..dd2c0c29d 100644 --- a/content/browser/media/capture/web_contents_audio_input_stream.h +++ b/content/browser/media/capture/web_contents_audio_input_stream.h
@@ -61,8 +61,7 @@ const std::string& device_id, const media::AudioParameters& params, const scoped_refptr<base::SingleThreadTaskRunner>& worker_task_runner, - AudioMirroringManager* audio_mirroring_manager, - bool is_duplication); + AudioMirroringManager* audio_mirroring_manager); private: friend class WebContentsAudioInputStreamTest;
diff --git a/content/browser/media/capture/web_contents_video_capture_device.cc b/content/browser/media/capture/web_contents_video_capture_device.cc index e475cbd..1f24693 100644 --- a/content/browser/media/capture/web_contents_video_capture_device.cc +++ b/content/browser/media/capture/web_contents_video_capture_device.cc
@@ -992,19 +992,18 @@ } // static -media::VideoCaptureDevice* WebContentsVideoCaptureDevice::Create( - const std::string& device_id) { +std::unique_ptr<media::VideoCaptureDevice> +WebContentsVideoCaptureDevice::Create(const std::string& device_id) { // Parse device_id into render_process_id and main_render_frame_id. - int render_process_id = -1; - int main_render_frame_id = -1; - if (!WebContentsMediaCaptureId::ExtractTabCaptureTarget( - device_id, &render_process_id, &main_render_frame_id)) { + WebContentsMediaCaptureId media_id; + if (!WebContentsMediaCaptureId::Parse(device_id, &media_id)) { return NULL; } - return new WebContentsVideoCaptureDevice( - render_process_id, main_render_frame_id, - WebContentsMediaCaptureId::IsAutoThrottlingOptionSet(device_id)); + return std::unique_ptr<media::VideoCaptureDevice>( + new WebContentsVideoCaptureDevice(media_id.render_process_id, + media_id.main_render_frame_id, + media_id.enable_auto_throttling)); } void WebContentsVideoCaptureDevice::AllocateAndStart(
diff --git a/content/browser/media/capture/web_contents_video_capture_device.h b/content/browser/media/capture/web_contents_video_capture_device.h index 6bcddfa9..6063f7e 100644 --- a/content/browser/media/capture/web_contents_video_capture_device.h +++ b/content/browser/media/capture/web_contents_video_capture_device.h
@@ -30,7 +30,8 @@ public: // Create a WebContentsVideoCaptureDevice instance from the given // |device_id|. Returns NULL if |device_id| is invalid. - static media::VideoCaptureDevice* Create(const std::string& device_id); + static std::unique_ptr<media::VideoCaptureDevice> Create( + const std::string& device_id); ~WebContentsVideoCaptureDevice() override;
diff --git a/content/browser/media/capture/web_contents_video_capture_device_unittest.cc b/content/browser/media/capture/web_contents_video_capture_device_unittest.cc index 36de0f2..f8ee4344 100644 --- a/content/browser/media/capture/web_contents_video_capture_device_unittest.cc +++ b/content/browser/media/capture/web_contents_video_capture_device_unittest.cc
@@ -634,10 +634,9 @@ web_contents_.reset( TestWebContents::Create(browser_context_.get(), site_instance.get())); RenderFrameHost* const main_frame = web_contents_->GetMainFrame(); - device_.reset(WebContentsVideoCaptureDevice::Create( - base::StringPrintf("web-contents-media-stream://%d:%d", - main_frame->GetProcess()->GetID(), - main_frame->GetRoutingID()))); + device_ = WebContentsVideoCaptureDevice::Create(base::StringPrintf( + "web-contents-media-stream://%d:%d", main_frame->GetProcess()->GetID(), + main_frame->GetRoutingID())); base::RunLoop().RunUntilIdle(); }
diff --git a/content/browser/memory/memory_coordinator.cc b/content/browser/memory/memory_coordinator.cc index 52ee2ec..622d8b9 100644 --- a/content/browser/memory/memory_coordinator.cc +++ b/content/browser/memory/memory_coordinator.cc
@@ -5,6 +5,9 @@ #include "content/browser/memory/memory_coordinator.h" #include "base/memory/memory_coordinator_client_registry.h" +#include "content/public/browser/content_browser_client.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/common/content_client.h" #include "content/public/common/content_features.h" namespace content { @@ -41,7 +44,9 @@ base::LeakySingletonTraits<MemoryCoordinator>>::get(); } -MemoryCoordinator::MemoryCoordinator() {} +MemoryCoordinator::MemoryCoordinator() + : delegate_(GetContentClient()->browser()->GetMemoryCoordinatorDelegate()) { +} MemoryCoordinator::~MemoryCoordinator() {} @@ -75,6 +80,11 @@ if (iter->second.memory_state == memory_state) return true; + // Can't suspend the given renderer. + if (memory_state == mojom::MemoryState::SUSPENDED && + !CanSuspendRenderer(render_process_id)) + return false; + // Update the internal state and send the message. iter->second.memory_state = memory_state; iter->second.handle->child()->OnStateChange(memory_state); @@ -103,6 +113,16 @@ children_.erase(render_process_id); } +bool MemoryCoordinator::CanSuspendRenderer(int render_process_id) { + // If there is no delegate (i.e. tests), renderers are always suspendable. + if (!delegate_) + return true; + auto* render_process_host = RenderProcessHost::FromID(render_process_id); + if (!render_process_host->IsProcessBackgrounded()) + return false; + return delegate_->CanSuspendBackgroundedRenderer(render_process_id); +} + void MemoryCoordinator::CreateChildInfoMapEntry( int render_process_id, std::unique_ptr<MemoryCoordinatorHandleImpl> handle) {
diff --git a/content/browser/memory/memory_coordinator.h b/content/browser/memory/memory_coordinator.h index f674ef5..65f4478 100644 --- a/content/browser/memory/memory_coordinator.h +++ b/content/browser/memory/memory_coordinator.h
@@ -10,6 +10,7 @@ #include "base/process/process_handle.h" #include "content/common/content_export.h" #include "content/common/memory_coordinator.mojom.h" +#include "content/public/browser/memory_coordinator_delegate.h" #include "mojo/public/cpp/bindings/binding.h" namespace content { @@ -59,6 +60,9 @@ // for testing. void OnConnectionError(int render_process_id); + // Returns true when a given renderer can be suspended. + bool CanSuspendRenderer(int render_process_id); + private: friend struct base::DefaultSingletonTraits<MemoryCoordinator>; @@ -86,6 +90,8 @@ // disconnected. ChildInfoMap children_; + std::unique_ptr<MemoryCoordinatorDelegate> delegate_; + DISALLOW_COPY_AND_ASSIGN(MemoryCoordinator); };
diff --git a/content/browser/renderer_host/media/audio_input_renderer_host.cc b/content/browser/renderer_host/media/audio_input_renderer_host.cc index 9008596..2894239 100644 --- a/content/browser/renderer_host/media/audio_input_renderer_host.cc +++ b/content/browser/renderer_host/media/audio_input_renderer_host.cc
@@ -427,7 +427,7 @@ // If we have successfully created the SyncWriter then assign it to the // entry and construct an AudioInputController. entry->writer.reset(writer.release()); - if (WebContentsMediaCaptureId::IsWebContentsDeviceId(device_id)) { + if (WebContentsMediaCaptureId::Parse(device_id, nullptr)) { // For MEDIA_DESKTOP_AUDIO_CAPTURE, the source is selected from picker // window, we do not mute the source audio. // For MEDIA_TAB_AUDIO_CAPTURE, the probable use case is Cast, we mute @@ -438,7 +438,7 @@ audio_manager_->GetTaskRunner(), this, WebContentsAudioInputStream::Create( device_id, audio_params, audio_manager_->GetWorkerTaskRunner(), - audio_mirroring_manager_, type == MEDIA_DESKTOP_AUDIO_CAPTURE), + audio_mirroring_manager_), entry->writer.get(), user_input_monitor_); // Only count for captures from desktop media picker dialog. if (entry->controller.get() && type == MEDIA_DESKTOP_AUDIO_CAPTURE)
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc index 0b44e5f..28fd3df 100644 --- a/content/browser/renderer_host/media/media_stream_manager.cc +++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -305,7 +305,7 @@ requesting_process_id, requesting_frame_id, page_request_id, security_origin.GetURL(), user_gesture, request_type, requested_audio_device_id, requested_video_device_id, audio_type_, - video_type_)); + video_type_, controls.disable_local_echo)); } // Creates a tab capture specific MediaStreamRequest object that is used by @@ -318,7 +318,7 @@ ui_request_.reset(new MediaStreamRequest( target_render_process_id, target_render_frame_id, page_request_id, security_origin.GetURL(), user_gesture, request_type, "", "", - audio_type_, video_type_)); + audio_type_, video_type_, controls.disable_local_echo)); } bool HasUIRequest() const { return ui_request_.get() != nullptr; } @@ -535,6 +535,18 @@ const std::string& label = AddRequest(request); + if (!generate_stream_test_callback_.is_null()) { + // The test callback is responsible to verify whether the |controls| is + // as expected. Then we need to finish getUserMedia and let Javascript + // access the result. + if (generate_stream_test_callback_.Run(controls)) { + FinalizeGenerateStream(label, request); + } else { + FinalizeRequestFailed(label, request, MEDIA_DEVICE_INVALID_STATE); + } + return; + } + // Post a task and handle the request asynchronously. The reason is that the // requester won't have a label for the request until this function returns // and thus can not handle a response. Using base::Unretained is safe since @@ -1179,11 +1191,9 @@ } // Customize controls for a WebContents based capture. - int target_render_process_id = 0; - int target_render_frame_id = 0; - - bool has_valid_device_id = WebContentsMediaCaptureId::ExtractTabCaptureTarget( - capture_device_id, &target_render_process_id, &target_render_frame_id); + content::WebContentsMediaCaptureId web_id; + bool has_valid_device_id = + WebContentsMediaCaptureId::Parse(capture_device_id, &web_id); if (!has_valid_device_id || (request->audio_type() != MEDIA_TAB_AUDIO_CAPTURE && request->audio_type() != MEDIA_NO_SERVICE) || @@ -1191,16 +1201,19 @@ request->video_type() != MEDIA_NO_SERVICE)) { return false; } - request->tab_capture_device_id = capture_device_id; + web_id.disable_local_echo = request->controls.disable_local_echo; - request->CreateTabCaptureUIRequest(target_render_process_id, - target_render_frame_id); + request->tab_capture_device_id = web_id.ToString(); + + request->CreateTabCaptureUIRequest(web_id.render_process_id, + web_id.main_render_frame_id); DVLOG(3) << "SetupTabCaptureRequest " - << ", {capture_device_id = " << capture_device_id << "}" - << ", {target_render_process_id = " << target_render_process_id + << ", {capture_device_id = " << capture_device_id << "}" + << ", {target_render_process_id = " << web_id.render_process_id << "}" - << ", {target_render_frame_id = " << target_render_frame_id << "}"; + << ", {target_render_frame_id = " << web_id.main_render_frame_id + << "}"; return true; } @@ -2031,4 +2044,9 @@ } } +void MediaStreamManager::SetGenerateStreamCallbackForTesting( + GenerateStreamTestCallback test_callback) { + generate_stream_test_callback_ = test_callback; +} + } // namespace content
diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h index 28fb1028..c448eaf 100644 --- a/content/browser/renderer_host/media/media_stream_manager.h +++ b/content/browser/renderer_host/media/media_stream_manager.h
@@ -78,6 +78,10 @@ std::unique_ptr<MediaStreamUIProxy> ui)> MediaRequestResponseCallback; + // Callback for testing. + typedef base::Callback<bool(const StreamControls&)> + GenerateStreamTestCallback; + // Adds |message| to native logs for outstanding device requests, for use by // render processes hosts whose corresponding render processes are requesting // logging from webrtcLoggingPrivate API. Safe to call from any thread. @@ -274,6 +278,9 @@ // See http://crbug.com/648183. void NotifyDeviceChangeSubscribers(MediaStreamType type); + void SetGenerateStreamCallbackForTesting( + GenerateStreamTestCallback test_callback); + private: // Contains all data needed to keep track of requests. class DeviceRequest; @@ -450,6 +457,8 @@ // Objects subscribed to changes in the set of media devices. std::vector<MediaStreamRequester*> device_change_subscribers_; + GenerateStreamTestCallback generate_stream_test_callback_; + DISALLOW_COPY_AND_ASSIGN(MediaStreamManager); };
diff --git a/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc b/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc index 9fd8b7e4..90fc678 100644 --- a/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
@@ -94,7 +94,7 @@ std::unique_ptr<MediaStreamRequest> request(new MediaStreamRequest( 0, 0, 0, GURL("http://origin/"), false, MEDIA_GENERATE_STREAM, std::string(), std::string(), MEDIA_DEVICE_AUDIO_CAPTURE, - MEDIA_DEVICE_VIDEO_CAPTURE)); + MEDIA_DEVICE_VIDEO_CAPTURE, false)); MediaStreamRequest* request_ptr = request.get(); proxy_->RequestAccess( std::move(request), @@ -122,7 +122,7 @@ std::unique_ptr<MediaStreamRequest> request(new MediaStreamRequest( 0, 0, 0, GURL("http://origin/"), false, MEDIA_GENERATE_STREAM, std::string(), std::string(), MEDIA_DEVICE_AUDIO_CAPTURE, - MEDIA_DEVICE_VIDEO_CAPTURE)); + MEDIA_DEVICE_VIDEO_CAPTURE, false)); MediaStreamRequest* request_ptr = request.get(); proxy_->RequestAccess( std::move(request), @@ -158,7 +158,7 @@ std::unique_ptr<MediaStreamRequest> request(new MediaStreamRequest( 0, 0, 0, GURL("http://origin/"), false, MEDIA_GENERATE_STREAM, std::string(), std::string(), MEDIA_DEVICE_AUDIO_CAPTURE, - MEDIA_DEVICE_VIDEO_CAPTURE)); + MEDIA_DEVICE_VIDEO_CAPTURE, false)); MediaStreamRequest* request_ptr = request.get(); proxy_->RequestAccess( std::move(request), @@ -182,7 +182,7 @@ std::unique_ptr<MediaStreamRequest> request(new MediaStreamRequest( 0, 0, 0, GURL("http://origin/"), false, MEDIA_GENERATE_STREAM, std::string(), std::string(), MEDIA_DEVICE_AUDIO_CAPTURE, - MEDIA_DEVICE_VIDEO_CAPTURE)); + MEDIA_DEVICE_VIDEO_CAPTURE, false)); MediaStreamRequest* request_ptr = request.get(); proxy_->RequestAccess( std::move(request), @@ -228,7 +228,7 @@ std::unique_ptr<MediaStreamRequest> request(new MediaStreamRequest( 0, 0, 0, GURL("http://origin/"), false, MEDIA_GENERATE_STREAM, std::string(), std::string(), MEDIA_NO_SERVICE, - MEDIA_DESKTOP_VIDEO_CAPTURE)); + MEDIA_DESKTOP_VIDEO_CAPTURE, false)); MediaStreamRequest* request_ptr = request.get(); proxy_->RequestAccess(
diff --git a/content/browser/renderer_host/media/video_capture_manager.cc b/content/browser/renderer_host/media/video_capture_manager.cc index b8aadb8..7cd548a 100644 --- a/content/browser/renderer_host/media/video_capture_manager.cc +++ b/content/browser/renderer_host/media/video_capture_manager.cc
@@ -594,7 +594,7 @@ DCHECK(IsOnDeviceThread()); std::unique_ptr<VideoCaptureDevice> video_capture_device; - video_capture_device.reset(WebContentsVideoCaptureDevice::Create(id)); + video_capture_device = WebContentsVideoCaptureDevice::Create(id); if (!video_capture_device) { device_client->OnError(FROM_HERE, "Could not create capture device"); @@ -622,7 +622,7 @@ } if (desktop_id.type == DesktopMediaID::TYPE_WEB_CONTENTS) { - video_capture_device.reset(WebContentsVideoCaptureDevice::Create(id)); + video_capture_device = WebContentsVideoCaptureDevice::Create(id); IncrementDesktopCaptureCounter(TAB_VIDEO_CAPTURER_CREATED); if (desktop_id.audio_share) { IncrementDesktopCaptureCounter(TAB_VIDEO_CAPTURER_CREATED_WITH_AUDIO);
diff --git a/content/browser/renderer_host/render_view_host_delegate.h b/content/browser/renderer_host/render_view_host_delegate.h index 2d47a71..52d0f84 100644 --- a/content/browser/renderer_host/render_view_host_delegate.h +++ b/content/browser/renderer_host/render_view_host_delegate.h
@@ -105,7 +105,6 @@ // The state for the page changed and should be updated. virtual void UpdateState(RenderViewHost* render_view_host, - int32_t page_id, const PageState& state) {} // The destination URL has changed should be updated.
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index 95852d6d..b4697ddc 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -255,7 +255,6 @@ delegate_(delegate), instance_(static_cast<SiteInstanceImpl*>(instance)), enabled_bindings_(0), - page_id_(-1), is_active_(!swapped_out), is_swapped_out_(swapped_out), main_frame_routing_id_(main_frame_routing_id), @@ -942,14 +941,7 @@ // decoupled. } -void RenderViewHostImpl::OnUpdateState(int32_t page_id, - const PageState& state) { - // If the following DCHECK fails, you have encountered a tricky edge-case that - // has evaded reproduction for a very long time. Please report what you were - // doing on http://crbug.com/407376, whether or not you can reproduce the - // failure. - DCHECK_EQ(page_id, page_id_); - +void RenderViewHostImpl::OnUpdateState(const PageState& state) { // Without this check, the renderer can trick the browser into using // filenames it can't access in a future session restore. auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); @@ -960,7 +952,7 @@ return; } - delegate_->UpdateState(this, page_id, state); + delegate_->UpdateState(this, state); } void RenderViewHostImpl::OnUpdateTargetURL(const GURL& url) {
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h index f8cce528..01871e8e 100644 --- a/content/browser/renderer_host/render_view_host_impl.h +++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -287,7 +287,7 @@ void OnShowWidget(int route_id, const gfx::Rect& initial_rect); void OnShowFullscreenWidget(int route_id); void OnRenderProcessGone(int status, int error_code); - void OnUpdateState(int32_t page_id, const PageState& state); + void OnUpdateState(const PageState& state); void OnUpdateTargetURL(const GURL& url); void OnClose(); void OnRequestMove(const gfx::Rect& pos); @@ -359,11 +359,6 @@ // See BindingsPolicy for details. int enabled_bindings_; - // The most recent page ID we've heard from the renderer process. This is - // used as context when other session history related IPCs arrive. - // TODO(creis): Allocate this in WebContents/NavigationController instead. - int32_t page_id_; - // Tracks whether this RenderViewHost is in an active state. False if the // main frame is pending swap out, pending deletion, or swapped out, because // it is not visible to the user in any of these cases.
diff --git a/content/browser/renderer_host/render_view_host_unittest.cc b/content/browser/renderer_host/render_view_host_unittest.cc index 6e57959..2a8eeb9 100644 --- a/content/browser/renderer_host/render_view_host_unittest.cc +++ b/content/browser/renderer_host/render_view_host_unittest.cc
@@ -195,12 +195,12 @@ EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file_path)); file_path = file_path.AppendASCII("foo"); EXPECT_EQ(0, process()->bad_msg_count()); - test_rvh()->TestOnUpdateStateWithFile(-1, file_path); + test_rvh()->TestOnUpdateStateWithFile(file_path); EXPECT_EQ(1, process()->bad_msg_count()); ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile( process()->GetID(), file_path); - test_rvh()->TestOnUpdateStateWithFile(-1, file_path); + test_rvh()->TestOnUpdateStateWithFile(file_path); EXPECT_EQ(1, process()->bad_msg_count()); }
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 9842629..b6f8ed73 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -4334,7 +4334,6 @@ } void WebContentsImpl::UpdateState(RenderViewHost* rvh, - int32_t page_id, const PageState& page_state) { DCHECK(!SiteIsolationPolicy::UseSubframeNavigationEntries()); @@ -4344,27 +4343,17 @@ if (rvh->GetDelegate()->GetAsWebContents() != this) return; - // We must be prepared to handle state updates for any page. They occur - // when the user is scrolling and entering form data, as well as when we're - // leaving a page, in which case our state may have already been moved to - // the next page. The navigation controller will look up the appropriate - // NavigationEntry and update it when it is notified via the delegate. - RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(rvh); - NavigationEntryImpl* entry = controller_.GetEntryWithPageID( - rvhi->GetSiteInstance(), page_id); - if (!entry) + if (!rvh->GetMainFrame()) { + // When UseSubframeNavigationEntries is turned off, state updates only come + // in on main frames. When UseSubframeNavigationEntries is turned on, + // UpdateStateForFrame() should have been called rather than this function. + NOTREACHED(); return; - - // Sanity check that ensures nav_entry_id and page_id point to the same - // navigation entry. - if (rvhi->GetMainFrame()) { - NavigationEntryImpl* new_entry = controller_.GetEntryWithUniqueID( - static_cast<RenderFrameHostImpl*>(rvhi->GetMainFrame()) - ->nav_entry_id()); - - DCHECK_EQ(entry, new_entry); } + NavigationEntryImpl* entry = controller_.GetEntryWithUniqueID( + static_cast<RenderFrameHostImpl*>(rvh->GetMainFrame())->nav_entry_id()); + if (page_state == entry->GetPageState()) return; // Nothing to update. entry->SetPageState(page_state); @@ -4587,7 +4576,6 @@ } void WebContentsImpl::UpdateTitle(RenderFrameHost* render_frame_host, - int32_t page_id, const base::string16& title, base::i18n::TextDirection title_direction) { // If we have a title, that's a pretty good indication that we've started @@ -4596,20 +4584,8 @@ // Try to find the navigation entry, which might not be the current one. // For example, it might be from a recently swapped out RFH. - NavigationEntryImpl* entry = controller_.GetEntryWithPageID( - render_frame_host->GetSiteInstance(), page_id); - - NavigationEntryImpl* new_entry = controller_.GetEntryWithUniqueID( + NavigationEntryImpl* entry = controller_.GetEntryWithUniqueID( static_cast<RenderFrameHostImpl*>(render_frame_host)->nav_entry_id()); - if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) { - // In out-of-process iframe enabled modes, page_id can't keep track of - // navigations in other processes, so we must use nav_entry_id. - // TODO(creis): Switch to use this as the default. - entry = new_entry; - } - // (In modes that have no out-of-process iframes, nav_entry_id and page_id - // will usually agree on which entry to update, but may disagree if commits - // from a previous RFH have been ignored, resetting the RFH's nav_entry_id.) // We can handle title updates when we don't have an entry in // UpdateTitleForEntry, but only if the update is from the current RVH.
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index e57408e..d26d541 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -474,7 +474,6 @@ void UpdateStateForFrame(RenderFrameHost* render_frame_host, const PageState& page_state) override; void UpdateTitle(RenderFrameHost* render_frame_host, - int32_t page_id, const base::string16& title, base::i18n::TextDirection title_direction) override; void UpdateEncoding(RenderFrameHost* render_frame_host, @@ -515,7 +514,6 @@ int error_code) override; void RenderViewDeleted(RenderViewHost* render_view_host) override; void UpdateState(RenderViewHost* render_view_host, - int32_t page_id, const PageState& page_state) override; void UpdateTargetURL(RenderViewHost* render_view_host, const GURL& url) override;
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc index b1373bd..9d43c05 100644 --- a/content/browser/web_contents/web_contents_impl_unittest.cc +++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -367,7 +367,7 @@ main_test_rfh()->SendNavigateWithParams(¶ms); - contents()->UpdateTitle(main_test_rfh(), 0, + contents()->UpdateTitle(main_test_rfh(), base::ASCIIToUTF16(" Lots O' Whitespace\n"), base::i18n::LEFT_TO_RIGHT); EXPECT_EQ(base::ASCIIToUTF16("Lots O' Whitespace"), contents()->GetTitle()); @@ -376,8 +376,7 @@ TEST_F(WebContentsImplTest, UpdateTitleBeforeFirstNavigation) { ASSERT_TRUE(controller().IsInitialNavigation()); const base::string16 title = base::ASCIIToUTF16("Initial Entry Title"); - contents()->UpdateTitle(main_test_rfh(), -1, title, - base::i18n::LEFT_TO_RIGHT); + contents()->UpdateTitle(main_test_rfh(), title, base::i18n::LEFT_TO_RIGHT); EXPECT_EQ(title, contents()->GetTitle()); } @@ -389,8 +388,7 @@ // Also test setting title while the first navigation is still pending. const base::string16 title = base::ASCIIToUTF16("Initial Entry Title"); - contents()->UpdateTitle(main_test_rfh(), -1, title, - base::i18n::LEFT_TO_RIGHT); + contents()->UpdateTitle(main_test_rfh(), title, base::i18n::LEFT_TO_RIGHT); EXPECT_EQ(title, contents()->GetTitle()); }
diff --git a/content/browser/webrtc/webrtc_getusermedia_browsertest.cc b/content/browser/webrtc/webrtc_getusermedia_browsertest.cc index 711c5ae..33e29451 100644 --- a/content/browser/webrtc/webrtc_getusermedia_browsertest.cc +++ b/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
@@ -13,6 +13,8 @@ #include "base/trace_event/trace_event_impl.h" #include "base/values.h" #include "build/build_config.h" +#include "content/browser/browser_main_loop.h" +#include "content/browser/renderer_host/media/media_stream_manager.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/browser/webrtc/webrtc_content_browsertest_base.h" #include "content/browser/webrtc/webrtc_internals.h" @@ -76,6 +78,23 @@ return function_name + "({" + audio_constraint + video_constraint + "});"; } +std::string GenerateGetUserMediaWithDisableLocalEcho( + const std::string& function_name, + const std::string& disable_local_echo) { + const std::string audio_constraint = + "audio:{mandatory: { chromeMediaSource : 'system', disableLocalEcho : " + + disable_local_echo + " }},"; + + const std::string video_constraint = + "video: { mandatory: { chromeMediaSource:'screen' }}"; + return function_name + "({" + audio_constraint + video_constraint + "});"; +} + +bool VerifyDisableLocalEcho(bool expect_value, + const content::StreamControls& controls) { + return expect_value == controls.disable_local_echo; +} + } // namespace namespace content { @@ -723,4 +742,32 @@ ExecuteJavascriptAndWaitForOk(call); } +IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, + DisableLocalEchoParameter) { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableExperimentalWebPlatformFeatures); + ASSERT_TRUE(embedded_test_server()->Start()); + + GURL url(embedded_test_server()->GetURL("/media/getusermedia.html")); + NavigateToURL(shell(), url); + + MediaStreamManager* manager = + BrowserMainLoop::GetInstance()->media_stream_manager(); + + manager->SetGenerateStreamCallbackForTesting( + base::Bind(&VerifyDisableLocalEcho, false)); + std::string call = GenerateGetUserMediaWithDisableLocalEcho( + "getUserMediaAndExpectSuccess", "false"); + ExecuteJavascriptAndWaitForOk(call); + + manager->SetGenerateStreamCallbackForTesting( + base::Bind(&VerifyDisableLocalEcho, true)); + call = GenerateGetUserMediaWithDisableLocalEcho( + "getUserMediaAndExpectSuccess", "true"); + ExecuteJavascriptAndWaitForOk(call); + + manager->SetGenerateStreamCallbackForTesting( + MediaStreamManager::GenerateStreamTestCallback()); +} + } // namespace content
diff --git a/content/browser/webui/web_ui_data_source_impl.cc b/content/browser/webui/web_ui_data_source_impl.cc index f62ade4..a5364fb 100644 --- a/content/browser/webui/web_ui_data_source_impl.cc +++ b/content/browser/webui/web_ui_data_source_impl.cc
@@ -10,6 +10,7 @@ #include <string> #include "base/bind.h" +#include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted_memory.h" #include "base/strings/string_util.h" @@ -74,9 +75,8 @@ return parent_->deny_xframe_options_; } bool IsGzipped(const std::string& path) const override { - if (!parent_->json_path_.empty() && path == parent_->json_path_) - return false; - return parent_->use_gzip_for_all_paths_; + return parent_->use_gzip_for_all_paths_ && + parent_->excluded_paths_.find(path) == parent_->excluded_paths_.end(); } private: @@ -147,7 +147,11 @@ } void WebUIDataSourceImpl::SetJsonPath(const std::string& path) { + DCHECK(json_path_.empty()); + DCHECK(!path.empty()); + json_path_ = path; + ExcludePathFromGzip(json_path_); } void WebUIDataSourceImpl::AddResourcePath(const std::string &path, @@ -168,6 +172,10 @@ replace_existing_source_ = false; } +void WebUIDataSourceImpl::ExcludePathFromGzip(const std::string& path) { + excluded_paths_.insert(path); +} + void WebUIDataSourceImpl::DisableContentSecurityPolicy() { add_csp_ = false; }
diff --git a/content/browser/webui/web_ui_data_source_impl.h b/content/browser/webui/web_ui_data_source_impl.h index 64515fee..387209eb 100644 --- a/content/browser/webui/web_ui_data_source_impl.h +++ b/content/browser/webui/web_ui_data_source_impl.h
@@ -9,6 +9,7 @@ #include <map> #include <string> +#include <unordered_set> #include "base/callback.h" #include "base/compiler_specific.h" @@ -49,6 +50,9 @@ void DisableDenyXFrameOptions() override; void DisableI18nAndUseGzipForAllPaths() override; + // When DisableI18nAndUseGzipForAllPaths is enabled, exclude the given |path|. + void ExcludePathFromGzip(const std::string& path); + protected: ~WebUIDataSourceImpl() override; @@ -85,6 +89,7 @@ int default_resource_; std::string json_path_; std::map<std::string, int> path_to_idr_map_; + std::unordered_set<std::string> excluded_paths_; // The |replacements_| is intended to replace |localized_strings_|. // TODO(dschuyler): phase out |localized_strings_| in Q1 2016. (Or rename // to |load_time_flags_| if the usage is reduced to storing flags only).
diff --git a/content/child/web_url_loader_impl.cc b/content/child/web_url_loader_impl.cc index e19bf5f..dd6425d 100644 --- a/content/child/web_url_loader_impl.cc +++ b/content/child/web_url_loader_impl.cc
@@ -276,11 +276,17 @@ const char* cipher; const char* mac; bool is_aead; + bool is_tls13; uint16_t cipher_suite = net::SSLConnectionStatusToCipherSuite(info.ssl_connection_status); net::SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, - cipher_suite); - if (mac == NULL) { + &is_tls13, cipher_suite); + if (key_exchange == nullptr) { + DCHECK(is_tls13); + key_exchange = ""; + } + + if (mac == nullptr) { DCHECK(is_aead); mac = ""; }
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index 36b0684..6c198ea 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -1067,9 +1067,6 @@ // window. IPC_MESSAGE_ROUTED1(FrameHostMsg_DidChangeOpener, int /* opener_routing_id */) -// Notifies the browser that a page id was assigned. -IPC_MESSAGE_ROUTED1(FrameHostMsg_DidAssignPageId, int32_t /* page_id */) - // Notifies the browser that sandbox flags have changed for a subframe of this // frame. IPC_MESSAGE_ROUTED2(FrameHostMsg_DidChangeSandboxFlags,
diff --git a/content/common/media/media_stream_messages.h b/content/common/media/media_stream_messages.h index 78c5e8c..d1f8d3b 100644 --- a/content/common/media/media_stream_messages.h +++ b/content/common/media/media_stream_messages.h
@@ -37,6 +37,7 @@ IPC_STRUCT_TRAITS_MEMBER(audio) IPC_STRUCT_TRAITS_MEMBER(video) IPC_STRUCT_TRAITS_MEMBER(hotword_enabled) + IPC_STRUCT_TRAITS_MEMBER(disable_local_echo) IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(content::StreamDeviceInfo)
diff --git a/content/common/media/media_stream_options.h b/content/common/media/media_stream_options.h index 5eb0606..f0aec2fd 100644 --- a/content/common/media/media_stream_options.h +++ b/content/common/media/media_stream_options.h
@@ -57,6 +57,7 @@ // Hotword functionality (chromeos only) // See crbug.com/564574 for discussion on possibly #ifdef'ing this out. bool hotword_enabled; // kMediaStreamAudioHotword = "googHotword"; + bool disable_local_echo; }; // StreamDeviceInfo describes information about a device.
diff --git a/content/common/origin_trials/trial_token.cc b/content/common/origin_trials/trial_token.cc index 2935d9c..ae11999 100644 --- a/content/common/origin_trials/trial_token.cc +++ b/content/common/origin_trials/trial_token.cc
@@ -157,6 +157,14 @@ return nullptr; } + // The |isSubdomain| flag is optional. If found, ensure it is a valid boolean. + bool is_subdomain = false; + if (datadict->HasKey("isSubdomain")) { + if (!datadict->GetBoolean("isSubdomain", &is_subdomain)) { + return nullptr; + } + } + // Ensure that the feature name is a valid string. if (feature_name.empty()) { return nullptr; @@ -168,10 +176,15 @@ } return base::WrapUnique( - new TrialToken(origin, feature_name, expiry_timestamp)); + new TrialToken(origin, is_subdomain, feature_name, expiry_timestamp)); } bool TrialToken::ValidateOrigin(const url::Origin& origin) const { + if (match_subdomains_) { + return origin.scheme() == origin_.scheme() && + origin.DomainIs(origin_.host()) && + origin.port() == origin_.port(); + } return origin == origin_; } @@ -203,9 +216,11 @@ } TrialToken::TrialToken(const url::Origin& origin, + bool match_subdomains, const std::string& feature_name, uint64_t expiry_timestamp) : origin_(origin), + match_subdomains_(match_subdomains), feature_name_(feature_name), expiry_time_(base::Time::FromDoubleT(expiry_timestamp)) {}
diff --git a/content/common/origin_trials/trial_token.h b/content/common/origin_trials/trial_token.h index 73eb361..943275639 100644 --- a/content/common/origin_trials/trial_token.h +++ b/content/common/origin_trials/trial_token.h
@@ -21,14 +21,13 @@ namespace content { -// The Experimental Framework (EF) provides limited access to experimental -// features, on a per-origin basis (origin trials). This class defines the trial -// token data structure, used to securely provide access to an experimental -// feature. +// The Origin Trials Framework (OT) provides limited access to experimental +// features, on a per-origin basis. This class defines the trial token data +// structure, used to securely provide access to an experimental feature. // -// Features are defined by string names, provided by the implementers. The EF +// Features are defined by string names, provided by the implementers. The OT // code does not maintain an enum or constant list for feature names. Instead, -// the EF validates the name provided by the feature implementation against any +// it validates the name provided by the feature implementation against any // provided tokens. // // More documentation on the token format can be found at @@ -58,6 +57,7 @@ const base::Time& now) const; url::Origin origin() { return origin_; } + bool match_subdomains() const { return match_subdomains_; } std::string feature_name() { return feature_name_; } base::Time expiry_time() { return expiry_time_; } @@ -92,12 +92,16 @@ private: TrialToken(const url::Origin& origin, + bool match_subdomains, const std::string& feature_name, uint64_t expiry_timestamp); // The origin for which this token is valid. Must be a secure origin. url::Origin origin_; + // Indicates if the token should match all subdomains of the origin. + bool match_subdomains_; + // The name of the experimental feature which this token enables. std::string feature_name_;
diff --git a/content/common/origin_trials/trial_token_unittest.cc b/content/common/origin_trials/trial_token_unittest.cc index 3c88134d..b5d396c 100644 --- a/content/common/origin_trials/trial_token_unittest.cc +++ b/content/common/origin_trials/trial_token_unittest.cc
@@ -65,13 +65,39 @@ "eGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5" "IjogMTQ1ODc2NjI3N30="; +// This is a good subdomain trial token, signed with the above test private key. +// Generate this token with the command (in tools/origin_trials): +// generate_token.py example.com Frobulate --is-subdomain +// --expire-timestamp=1458766277 +const char* kSampleSubdomainToken = + "Auu+j9nXAQoy5+t00MiWakZwFExcdNC8ENkRdK1gL4OMFHS0AbZCscslDTcP1fjN" + "FjpbmQG+VCPk1NrldVXZng4AAABoeyJvcmlnaW4iOiAiaHR0cHM6Ly9leGFtcGxl" + "LmNvbTo0NDMiLCAiaXNTdWJkb21haW4iOiB0cnVlLCAiZmVhdHVyZSI6ICJGcm9i" + "dWxhdGUiLCAiZXhwaXJ5IjogMTQ1ODc2NjI3N30="; + +// This is a good trial token, explicitly not a subdomain, signed with the above +// test private key. Generate this token with the command: +// generate_token.py valid.example.com Frobulate --no-subdomain +// --expire-timestamp=1458766277 +const char* kSampleNonSubdomainToken = + "AreD979D7tO0luSZTr1+/+J6E0SSj/GEUyLK41o1hXFzXw1R7Z1hCDHs0gXWVSu1" + "lvH52Winvy39tHbsU2gJJQYAAABveyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5l" + "eGFtcGxlLmNvbTo0NDMiLCAiaXNTdWJkb21haW4iOiBmYWxzZSwgImZlYXR1cmUi" + "OiAiRnJvYnVsYXRlIiwgImV4cGlyeSI6IDE0NTg3NjYyNzd9"; + const char* kExpectedFeatureName = "Frobulate"; const char* kExpectedOrigin = "https://valid.example.com"; +const char* kExpectedSubdomainOrigin = "https://example.com"; +const char* kExpectedMultipleSubdomainOrigin = + "https://part1.part2.part3.example.com"; const uint64_t kExpectedExpiry = 1458766277; // The token should not be valid for this origin, or for this feature. const char* kInvalidOrigin = "https://invalid.example.com"; const char* kInsecureOrigin = "http://valid.example.com"; +const char* kIncorrectPortOrigin = "https://valid.example.com:444"; +const char* kIncorrectDomainOrigin = "https://valid.example2.com"; +const char* kInvalidTLDOrigin = "https://com"; const char* kInvalidFeatureName = "Grokalyze"; // The token should be valid if the current time is kValidTimestamp or earlier. @@ -112,6 +138,14 @@ "{\"origin\": \"https://valid.example.com:443\", \"feature\": " "\"Frobulate\", \"expiry\": 1458766277}"; +const char kSampleNonSubdomainTokenJSON[] = + "{\"origin\": \"https://valid.example.com:443\", \"isSubdomain\": false, " + "\"feature\": \"Frobulate\", \"expiry\": 1458766277}"; + +const char kSampleSubdomainTokenJSON[] = + "{\"origin\": \"https://example.com:443\", \"isSubdomain\": true, " + "\"feature\": \"Frobulate\", \"expiry\": 1458766277}"; + // Various ill-formed trial tokens. These should all fail to parse. const char* kInvalidTokens[] = { // Invalid - Not JSON at all @@ -126,13 +160,17 @@ "{}", "{\"something\": 1}", "{\"origin\": \"https://a.a\"}", - "{\"origin\": \"https://a.a\", \"feature\": \"a\"}" + "{\"origin\": \"https://a.a\", \"feature\": \"a\"}", "{\"origin\": \"https://a.a\", \"expiry\": 1458766277}", "{\"feature\": \"FeatureName\", \"expiry\": 1458766277}", // Incorrect types "{\"origin\": 1, \"feature\": \"a\", \"expiry\": 1458766277}", "{\"origin\": \"https://a.a\", \"feature\": 1, \"expiry\": 1458766277}", "{\"origin\": \"https://a.a\", \"feature\": \"a\", \"expiry\": \"1\"}", + "{\"origin\": \"https://a.a\", \"isSubdomain\": \"true\", \"feature\": " + "\"a\", \"expiry\": 1458766277}", + "{\"origin\": \"https://a.a\", \"isSubdomain\": 1, \"feature\": \"a\", " + "\"expiry\": 1458766277}", // Negative expiry timestamp "{\"origin\": \"https://a.a\", \"feature\": \"a\", \"expiry\": -1}", // Origin not a proper origin URL @@ -140,7 +178,8 @@ "{\"origin\": \"data:text/plain,abcdef\", \"feature\": \"a\", \"expiry\": " "1458766277}", "{\"origin\": \"javascript:alert(1)\", \"feature\": \"a\", \"expiry\": " - "1458766277}"}; + "1458766277}", +}; } // namespace @@ -148,8 +187,14 @@ public: TrialTokenTest() : expected_origin_(GURL(kExpectedOrigin)), + expected_subdomain_origin_(GURL(kExpectedSubdomainOrigin)), + expected_multiple_subdomain_origin_( + GURL(kExpectedMultipleSubdomainOrigin)), invalid_origin_(GURL(kInvalidOrigin)), insecure_origin_(GURL(kInsecureOrigin)), + incorrect_port_origin_(GURL(kIncorrectPortOrigin)), + incorrect_domain_origin_(GURL(kIncorrectDomainOrigin)), + invalid_tld_origin_(GURL(kInvalidTLDOrigin)), expected_expiry_(base::Time::FromDoubleT(kExpectedExpiry)), valid_timestamp_(base::Time::FromDoubleT(kValidTimestamp)), invalid_timestamp_(base::Time::FromDoubleT(kInvalidTimestamp)), @@ -194,8 +239,13 @@ base::StringPiece incorrect_public_key() { return incorrect_public_key_; } const url::Origin expected_origin_; + const url::Origin expected_subdomain_origin_; + const url::Origin expected_multiple_subdomain_origin_; const url::Origin invalid_origin_; const url::Origin insecure_origin_; + const url::Origin incorrect_port_origin_; + const url::Origin incorrect_domain_origin_; + const url::Origin invalid_tld_origin_; const base::Time expected_expiry_; const base::Time valid_timestamp_; @@ -220,6 +270,22 @@ EXPECT_STREQ(kSampleTokenJSON, token_payload.c_str()); } +TEST_F(TrialTokenTest, ValidateSubdomainValidSignature) { + std::string token_payload; + blink::WebOriginTrialTokenStatus status = + Extract(kSampleSubdomainToken, correct_public_key(), &token_payload); + ASSERT_EQ(blink::WebOriginTrialTokenStatus::Success, status); + EXPECT_STREQ(kSampleSubdomainTokenJSON, token_payload.c_str()); +} + +TEST_F(TrialTokenTest, ValidateNonSubdomainValidSignature) { + std::string token_payload; + blink::WebOriginTrialTokenStatus status = + Extract(kSampleNonSubdomainToken, correct_public_key(), &token_payload); + ASSERT_EQ(blink::WebOriginTrialTokenStatus::Success, status); + EXPECT_STREQ(kSampleNonSubdomainTokenJSON, token_payload.c_str()); +} + TEST_F(TrialTokenTest, ValidateInvalidSignature) { blink::WebOriginTrialTokenStatus status = ExtractIgnorePayload(kInvalidSignatureToken, correct_public_key()); @@ -274,16 +340,39 @@ std::unique_ptr<TrialToken> token = Parse(kSampleTokenJSON); ASSERT_TRUE(token); EXPECT_EQ(kExpectedFeatureName, token->feature_name()); + EXPECT_FALSE(token->match_subdomains()); EXPECT_EQ(expected_origin_, token->origin()); EXPECT_EQ(expected_expiry_, token->expiry_time()); } +TEST_F(TrialTokenTest, ParseValidNonSubdomainToken) { + std::unique_ptr<TrialToken> token = Parse(kSampleNonSubdomainTokenJSON); + ASSERT_TRUE(token); + EXPECT_EQ(kExpectedFeatureName, token->feature_name()); + EXPECT_FALSE(token->match_subdomains()); + EXPECT_EQ(expected_origin_, token->origin()); + EXPECT_EQ(expected_expiry_, token->expiry_time()); +} + +TEST_F(TrialTokenTest, ParseValidSubdomainToken) { + std::unique_ptr<TrialToken> token = Parse(kSampleSubdomainTokenJSON); + ASSERT_TRUE(token); + EXPECT_EQ(kExpectedFeatureName, token->feature_name()); + EXPECT_TRUE(token->match_subdomains()); + EXPECT_EQ(kExpectedSubdomainOrigin, token->origin().Serialize()); + EXPECT_EQ(expected_subdomain_origin_, token->origin()); + EXPECT_EQ(expected_expiry_, token->expiry_time()); +} + TEST_F(TrialTokenTest, ValidateValidToken) { std::unique_ptr<TrialToken> token = Parse(kSampleTokenJSON); ASSERT_TRUE(token); EXPECT_TRUE(ValidateOrigin(token.get(), expected_origin_)); EXPECT_FALSE(ValidateOrigin(token.get(), invalid_origin_)); EXPECT_FALSE(ValidateOrigin(token.get(), insecure_origin_)); + EXPECT_FALSE(ValidateOrigin(token.get(), incorrect_port_origin_)); + EXPECT_FALSE(ValidateOrigin(token.get(), incorrect_domain_origin_)); + EXPECT_FALSE(ValidateOrigin(token.get(), invalid_tld_origin_)); EXPECT_TRUE(ValidateFeatureName(token.get(), kExpectedFeatureName)); EXPECT_FALSE(ValidateFeatureName(token.get(), kInvalidFeatureName)); EXPECT_FALSE(ValidateFeatureName( @@ -294,6 +383,18 @@ EXPECT_FALSE(ValidateDate(token.get(), invalid_timestamp_)); } +TEST_F(TrialTokenTest, ValidateValidSubdomainToken) { + std::unique_ptr<TrialToken> token = Parse(kSampleSubdomainTokenJSON); + ASSERT_TRUE(token); + EXPECT_TRUE(ValidateOrigin(token.get(), expected_origin_)); + EXPECT_TRUE(ValidateOrigin(token.get(), expected_subdomain_origin_)); + EXPECT_TRUE(ValidateOrigin(token.get(), expected_multiple_subdomain_origin_)); + EXPECT_FALSE(ValidateOrigin(token.get(), insecure_origin_)); + EXPECT_FALSE(ValidateOrigin(token.get(), incorrect_port_origin_)); + EXPECT_FALSE(ValidateOrigin(token.get(), incorrect_domain_origin_)); + EXPECT_FALSE(ValidateOrigin(token.get(), invalid_tld_origin_)); +} + TEST_F(TrialTokenTest, TokenIsValid) { std::unique_ptr<TrialToken> token = Parse(kSampleTokenJSON); ASSERT_TRUE(token); @@ -303,6 +404,28 @@ token->IsValid(invalid_origin_, valid_timestamp_)); EXPECT_EQ(blink::WebOriginTrialTokenStatus::WrongOrigin, token->IsValid(insecure_origin_, valid_timestamp_)); + EXPECT_EQ(blink::WebOriginTrialTokenStatus::WrongOrigin, + token->IsValid(incorrect_port_origin_, valid_timestamp_)); + EXPECT_EQ(blink::WebOriginTrialTokenStatus::Expired, + token->IsValid(expected_origin_, invalid_timestamp_)); +} + +TEST_F(TrialTokenTest, SubdomainTokenIsValid) { + std::unique_ptr<TrialToken> token = Parse(kSampleSubdomainTokenJSON); + ASSERT_TRUE(token); + EXPECT_EQ(blink::WebOriginTrialTokenStatus::Success, + token->IsValid(expected_origin_, valid_timestamp_)); + EXPECT_EQ(blink::WebOriginTrialTokenStatus::Success, + token->IsValid(expected_subdomain_origin_, valid_timestamp_)); + EXPECT_EQ( + blink::WebOriginTrialTokenStatus::Success, + token->IsValid(expected_multiple_subdomain_origin_, valid_timestamp_)); + EXPECT_EQ(blink::WebOriginTrialTokenStatus::WrongOrigin, + token->IsValid(incorrect_domain_origin_, valid_timestamp_)); + EXPECT_EQ(blink::WebOriginTrialTokenStatus::WrongOrigin, + token->IsValid(insecure_origin_, valid_timestamp_)); + EXPECT_EQ(blink::WebOriginTrialTokenStatus::WrongOrigin, + token->IsValid(incorrect_port_origin_, valid_timestamp_)); EXPECT_EQ(blink::WebOriginTrialTokenStatus::Expired, token->IsValid(expected_origin_, invalid_timestamp_)); }
diff --git a/content/common/swapped_out_messages.cc b/content/common/swapped_out_messages.cc index 39ba68f..34ce47ba 100644 --- a/content/common/swapped_out_messages.cc +++ b/content/common/swapped_out_messages.cc
@@ -43,9 +43,6 @@ case FrameHostMsg_DomOperationResponse::ID: // Input events propagate from parent to child. case FrameHostMsg_ForwardInputEvent::ID: - // The browser should always have an accurate mirror of the renderer's - // notion of the current page id. - case FrameHostMsg_DidAssignPageId::ID: // A swapped-out frame's opener might be updated with window.open. case FrameHostMsg_DidChangeOpener::ID: // For handling pop-ups from cross-site frames.
diff --git a/content/common/view_messages.h b/content/common/view_messages.h index 56d2fc5..c1720c0 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h
@@ -736,9 +736,7 @@ IPC_MESSAGE_ROUTED0(ViewHostMsg_ClosePage_ACK) // Notifies the browser that we have session history information. -// page_id: unique ID that allows us to distinguish between history entries. -IPC_MESSAGE_ROUTED2(ViewHostMsg_UpdateState, - int32_t /* page_id */, +IPC_MESSAGE_ROUTED1(ViewHostMsg_UpdateState, content::PageState /* state */) // Notifies the browser that we want to show a destination url for a potential
diff --git a/content/content_resources.grd b/content/content_resources.grd index cd40e2c5..030506ba 100644 --- a/content/content_resources.grd +++ b/content/content_resources.grd
@@ -10,9 +10,9 @@ <translations /> <release seq="1"> <includes> - <include name="IDR_ACCESSIBILITY_HTML" file="browser/resources/accessibility/accessibility.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> - <include name="IDR_ACCESSIBILITY_CSS" file="browser/resources/accessibility/accessibility.css" type="BINDATA" /> - <include name="IDR_ACCESSIBILITY_JS" file="browser/resources/accessibility/accessibility.js" flattenhtml="true" type="BINDATA" /> + <include name="IDR_ACCESSIBILITY_HTML" file="browser/resources/accessibility/accessibility.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" /> + <include name="IDR_ACCESSIBILITY_CSS" file="browser/resources/accessibility/accessibility.css" compress="gzip" type="BINDATA" /> + <include name="IDR_ACCESSIBILITY_JS" file="browser/resources/accessibility/accessibility.js" flattenhtml="true" compress="gzip" type="BINDATA" /> <include name="IDR_APPCACHE_INTERNALS_HTML" file="browser/resources/appcache/appcache_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" /> <include name="IDR_APPCACHE_INTERNALS_JS" file="browser/resources/appcache/appcache_internals.js" flattenhtml="false" compress="gzip" type="BINDATA" /> <include name="IDR_APPCACHE_INTERNALS_CSS" file="browser/resources/appcache/appcache_internals.css" flattenhtml="true" compress="gzip" type="BINDATA" />
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java index 80faa598..1d9e1cd1d 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
@@ -96,7 +96,8 @@ mCallbackContainer = new TestCallbackHelperContainer(mContentViewCore); DOMUtils.waitForNonZeroNodeBounds(mWebContents, "input_text"); - DOMUtils.clickNode(this, mContentViewCore, "input_text"); + boolean result = DOMUtils.clickNode(this, mContentViewCore, "input_text"); + assertEquals("Failed to dispatch touch event.", true, result); assertWaitForKeyboardStatus(true); mConnection = getInputConnection();
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index 9813c67..60669a87 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -134,6 +134,7 @@ "media_capture_devices.h", "media_device_id.cc", "media_device_id.h", + "memory_coordinator_delegate.h", "memory_pressure_controller.cc", "memory_pressure_controller.h", "message_port_delegate.h",
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index c6a2bec8..5ebc0170 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc
@@ -8,6 +8,7 @@ #include "base/guid.h" #include "build/build_config.h" #include "content/public/browser/client_certificate_delegate.h" +#include "content/public/browser/memory_coordinator_delegate.h" #include "content/public/browser/navigation_ui_data.h" #include "content/public/browser/vpn_service_proxy.h" #include "content/public/common/sandbox_type.h" @@ -424,4 +425,9 @@ return nullptr; } +std::unique_ptr<MemoryCoordinatorDelegate> +ContentBrowserClient::GetMemoryCoordinatorDelegate() { + return std::unique_ptr<MemoryCoordinatorDelegate>(); +} + } // namespace content
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index 41b22142..af10e53 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -114,6 +114,7 @@ class GpuProcessHost; class LocationProvider; class MediaObserver; +class MemoryCoordinatorDelegate; class NavigationHandle; class NavigationUIData; class PlatformNotificationService; @@ -775,6 +776,10 @@ virtual base::string16 GetAppContainerSidForSandboxType( int sandbox_type) const; #endif + + // Returns an instance of MemoryCoordinatorDelegate. + virtual std::unique_ptr<MemoryCoordinatorDelegate> + GetMemoryCoordinatorDelegate(); }; } // namespace content
diff --git a/content/public/browser/desktop_media_id.cc b/content/public/browser/desktop_media_id.cc index 8a20598..6c0027d4 100644 --- a/content/public/browser/desktop_media_id.cc +++ b/content/public/browser/desktop_media_id.cc
@@ -129,8 +129,8 @@ // window:"window_id:aura_id". DesktopMediaID DesktopMediaID::Parse(const std::string& str) { // For WebContents type. - WebContentsMediaCaptureId web_id = WebContentsMediaCaptureId::Parse(str); - if (!web_id.is_null()) + WebContentsMediaCaptureId web_id; + if (WebContentsMediaCaptureId::Parse(str, &web_id)) return DesktopMediaID(TYPE_WEB_CONTENTS, 0, web_id); // For screen and window types.
diff --git a/content/public/browser/memory_coordinator_delegate.h b/content/public/browser/memory_coordinator_delegate.h new file mode 100644 index 0000000..32758d9 --- /dev/null +++ b/content/public/browser/memory_coordinator_delegate.h
@@ -0,0 +1,23 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_PUBLIC_BROWSER_MEMORY_COORDINATOR_DELEGATE_H_ +#define CONTENT_PUBLIC_BROWSER_MEMORY_COORDINATOR_DELEGATE_H_ + +#include "content/common/content_export.h" + +namespace content { + +// A delegate class which is used by the memory coordinator. +class CONTENT_EXPORT MemoryCoordinatorDelegate { + public: + virtual ~MemoryCoordinatorDelegate() {} + + // Returns true when a given backgrounded renderer process can be suspended. + virtual bool CanSuspendBackgroundedRenderer(int render_process_id) = 0; +}; + +} // namespace content + +#endif // CONTENT_PUBLIC_BROWSER_MEMORY_COORDINATOR_DELEGATE_H_
diff --git a/content/public/browser/web_contents_media_capture_id.cc b/content/public/browser/web_contents_media_capture_id.cc index d9b107b..2835818b 100644 --- a/content/public/browser/web_contents_media_capture_id.cc +++ b/content/public/browser/web_contents_media_capture_id.cc
@@ -10,66 +10,16 @@ #include "base/strings/string_piece.h" #include "base/strings/string_util.h" -namespace content { -const char kWebContentsCaptureScheme[] = "web-contents-media-stream://"; -static char kEnableThrottlingFlag[] = "?throttling=auto"; +namespace { +constexpr char kWebContentsCaptureScheme[] = "web-contents-media-stream://"; +constexpr char kEnableThrottlingFlag[] = "throttling=auto"; +constexpr char kDisableLocalEchoFlag[] = "local_echo=false"; +constexpr char kOptionStart = '?'; +constexpr char kOptionSeparator = '&'; -bool WebContentsMediaCaptureId::operator<( - const WebContentsMediaCaptureId& other) const { - return std::tie(render_process_id, main_render_frame_id, - enable_auto_throttling) < - std::tie(other.render_process_id, other.main_render_frame_id, - other.enable_auto_throttling); -} - -bool WebContentsMediaCaptureId::operator==( - const WebContentsMediaCaptureId& other) const { - return std::tie(render_process_id, main_render_frame_id, - enable_auto_throttling) == - std::tie(other.render_process_id, other.main_render_frame_id, - other.enable_auto_throttling); -} - -bool WebContentsMediaCaptureId::is_null() const { - return (render_process_id < 0) || (main_render_frame_id < 0); -} - -std::string WebContentsMediaCaptureId::ToString() const { - std::string s = kWebContentsCaptureScheme; - s.append(base::Int64ToString(render_process_id)); - s.append(":"); - s.append(base::Int64ToString(main_render_frame_id)); - - if (enable_auto_throttling) - s.append(kEnableThrottlingFlag); - - return s; -} - -// static -WebContentsMediaCaptureId WebContentsMediaCaptureId::Parse( - const std::string& str) { - int render_process_id; - int main_render_frame_id; - if (!ExtractTabCaptureTarget(str, &render_process_id, &main_render_frame_id)) - return WebContentsMediaCaptureId(); - - return WebContentsMediaCaptureId(render_process_id, main_render_frame_id, - IsAutoThrottlingOptionSet(str)); -} - -// static -bool WebContentsMediaCaptureId::IsWebContentsDeviceId( - const std::string& device_id) { - int ignored; - return ExtractTabCaptureTarget(device_id, &ignored, &ignored); -} - -// static -bool WebContentsMediaCaptureId::ExtractTabCaptureTarget( - const std::string& device_id_param, - int* render_process_id, - int* main_render_frame_id) { +bool ExtractTabCaptureTarget(const std::string& device_id_param, + int* render_process_id, + int* main_render_frame_id) { const std::string device_scheme = kWebContentsCaptureScheme; if (!base::StartsWith(device_id_param, device_scheme, base::CompareCase::SENSITIVE)) @@ -92,21 +42,109 @@ base::StringToInt(component2, main_render_frame_id)); } -// static -bool WebContentsMediaCaptureId::IsAutoThrottlingOptionSet( - const std::string& device_id) { - if (!IsWebContentsDeviceId(device_id)) - return false; +bool ExtractOptions(const std::string& device_id, + bool* auto_throttling, + bool* disable_local_echo) { + DCHECK(auto_throttling); + DCHECK(disable_local_echo); + + *auto_throttling = false; + *disable_local_echo = false; // Find the option part of the string and just do a naive string compare since // there are no other options in the |device_id| to account for (at the time // of this writing). - const size_t option_pos = device_id.find('?'); + size_t option_pos = device_id.find(kOptionStart); if (option_pos == std::string::npos) - return false; - const base::StringPiece component(device_id.data() + option_pos, - device_id.length() - option_pos); - return component.compare(kEnableThrottlingFlag) == 0; + return true; + + size_t option_pos_end; + while (option_pos < device_id.length()) { + option_pos_end = device_id.find(kOptionSeparator, option_pos + 1); + if (option_pos_end == std::string::npos) + option_pos_end = device_id.length(); + const base::StringPiece component(device_id.data() + option_pos + 1, + option_pos_end - option_pos - 1); + + if (component.compare(kEnableThrottlingFlag) == 0) + *auto_throttling = true; + else if (component.compare(kDisableLocalEchoFlag) == 0) + *disable_local_echo = true; + else // Some unknown parameter is specified, and thus this ID is invalid. + return false; + + option_pos = option_pos_end; + } + return true; } +} // namespace + +namespace content { + +bool WebContentsMediaCaptureId::operator<( + const WebContentsMediaCaptureId& other) const { + return std::tie(render_process_id, main_render_frame_id, + enable_auto_throttling, disable_local_echo) < + std::tie(other.render_process_id, other.main_render_frame_id, + other.enable_auto_throttling, other.disable_local_echo); +} + +bool WebContentsMediaCaptureId::operator==( + const WebContentsMediaCaptureId& other) const { + return std::tie(render_process_id, main_render_frame_id, + enable_auto_throttling, disable_local_echo) == + std::tie(other.render_process_id, other.main_render_frame_id, + other.enable_auto_throttling, other.disable_local_echo); +} + +bool WebContentsMediaCaptureId::is_null() const { + return (render_process_id < 0) || (main_render_frame_id < 0); +} + +std::string WebContentsMediaCaptureId::ToString() const { + std::string s = kWebContentsCaptureScheme; + s.append(base::Int64ToString(render_process_id)); + s.append(":"); + s.append(base::Int64ToString(main_render_frame_id)); + + char connector = kOptionStart; + if (enable_auto_throttling) { + s += connector; + s.append(kEnableThrottlingFlag); + connector = kOptionSeparator; + } + + if (disable_local_echo) { + s += connector; + s.append(kDisableLocalEchoFlag); + connector = kOptionSeparator; + } + + return s; +} + +// static +bool WebContentsMediaCaptureId::Parse(const std::string& str, + WebContentsMediaCaptureId* output_id) { + int render_process_id; + int main_render_frame_id; + if (!ExtractTabCaptureTarget(str, &render_process_id, &main_render_frame_id)) + return false; + + bool auto_throttling, disable_local_echo; + if (!ExtractOptions(str, &auto_throttling, &disable_local_echo)) + return false; + + if (output_id) { + output_id->render_process_id = render_process_id; + output_id->main_render_frame_id = main_render_frame_id; + output_id->enable_auto_throttling = auto_throttling; + output_id->disable_local_echo = disable_local_echo; + } + + return true; +} + + } // namespace content
diff --git a/content/public/browser/web_contents_media_capture_id.h b/content/public/browser/web_contents_media_capture_id.h index 84d91db..dfc02e4 100644 --- a/content/public/browser/web_contents_media_capture_id.h +++ b/content/public/browser/web_contents_media_capture_id.h
@@ -21,10 +21,12 @@ WebContentsMediaCaptureId(int render_process_id, int main_render_frame_id, - bool enable_auto_throttling) + bool enable_auto_throttling, + bool disable_local_echo) : render_process_id(render_process_id), main_render_frame_id(main_render_frame_id), - enable_auto_throttling(enable_auto_throttling) {} + enable_auto_throttling(enable_auto_throttling), + disable_local_echo(disable_local_echo) {} bool operator<(const WebContentsMediaCaptureId& other) const; bool operator==(const WebContentsMediaCaptureId& other) const; @@ -39,22 +41,15 @@ int main_render_frame_id = MSG_ROUTING_NONE; bool enable_auto_throttling = false; + bool disable_local_echo = false; + // TODO(qiangchen): Pass structured ID along code paths, instead of doing + // string conversion back and forth. See crbug/648666. // Create WebContentsMediaCaptureId based on a string. - static WebContentsMediaCaptureId Parse(const std::string& str); - - // Check whether the device id indicates that this is a web contents stream. - static bool IsWebContentsDeviceId(const std::string& device_id); - - // Function to extract the target render frame id's from a media stream - // request's device id. - static bool ExtractTabCaptureTarget(const std::string& device_id, - int* render_process_id, - int* main_render_frame_id); - - // Parses the media stream request |device_id| and returns true if both 1) the - // format is valid, and 2) the throttling option is set to auto. - static bool IsAutoThrottlingOptionSet(const std::string& device_id); + // Return false if the input string does not represent a + // WebContentsMediaCaptureId. + static bool Parse(const std::string& str, + WebContentsMediaCaptureId* output_id); }; } // namespace content
diff --git a/content/public/common/media_stream_request.cc b/content/public/common/media_stream_request.cc index 9725335..a79cbd8 100644 --- a/content/public/common/media_stream_request.cc +++ b/content/public/common/media_stream_request.cc
@@ -126,7 +126,8 @@ const std::string& requested_audio_device_id, const std::string& requested_video_device_id, MediaStreamType audio_type, - MediaStreamType video_type) + MediaStreamType video_type, + bool disable_local_echo) : render_process_id(render_process_id), render_frame_id(render_frame_id), page_request_id(page_request_id), @@ -137,8 +138,8 @@ requested_video_device_id(requested_video_device_id), audio_type(audio_type), video_type(video_type), - all_ancestors_have_same_origin(false) { -} + disable_local_echo(disable_local_echo), + all_ancestors_have_same_origin(false) {} MediaStreamRequest::MediaStreamRequest(const MediaStreamRequest& other) = default;
diff --git a/content/public/common/media_stream_request.h b/content/public/common/media_stream_request.h index 71188ad..2af3357 100644 --- a/content/public/common/media_stream_request.h +++ b/content/public/common/media_stream_request.h
@@ -204,17 +204,17 @@ // Tab-only stuff and Pepper-only stuff being passed around to all clients, // which is icky. struct CONTENT_EXPORT MediaStreamRequest { - MediaStreamRequest( - int render_process_id, - int render_frame_id, - int page_request_id, - const GURL& security_origin, - bool user_gesture, - MediaStreamRequestType request_type, - const std::string& requested_audio_device_id, - const std::string& requested_video_device_id, - MediaStreamType audio_type, - MediaStreamType video_type); + MediaStreamRequest(int render_process_id, + int render_frame_id, + int page_request_id, + const GURL& security_origin, + bool user_gesture, + MediaStreamRequestType request_type, + const std::string& requested_audio_device_id, + const std::string& requested_video_device_id, + MediaStreamType audio_type, + MediaStreamType video_type, + bool disable_local_echo); MediaStreamRequest(const MediaStreamRequest& other); @@ -256,6 +256,10 @@ // Flag to indicate if the request contains video. MediaStreamType video_type; + // Flag for desktop or tab share to indicate whether to prevent the captured + // audio being played out locally. + bool disable_local_echo; + // True if all ancestors of the requesting frame have the same origin. bool all_ancestors_have_same_origin; };
diff --git a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/DOMUtils.java b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/DOMUtils.java index 9b457de..4429cf7 100644 --- a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/DOMUtils.java +++ b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/DOMUtils.java
@@ -231,12 +231,13 @@ * @param viewCore The ContentViewCore in which the node lives. * @param nodeId The id of the node. */ - public static void clickNode(ActivityInstrumentationTestCase2 activityTestCase, + public static boolean clickNode(ActivityInstrumentationTestCase2 activityTestCase, final ContentViewCore viewCore, String nodeId) throws InterruptedException, TimeoutException { scrollNodeIntoView(viewCore.getWebContents(), nodeId); int[] clickTarget = getClickTargetForNode(viewCore, nodeId); - TouchCommon.singleClickView(viewCore.getContainerView(), clickTarget[0], clickTarget[1]); + return TouchCommon.singleClickView( + viewCore.getContainerView(), clickTarget[0], clickTarget[1]); } /**
diff --git a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TouchCommon.java b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TouchCommon.java index f0785df..827ee504 100644 --- a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TouchCommon.java +++ b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TouchCommon.java
@@ -108,11 +108,11 @@ * @param x X coordinate, relative to v. * @param y Y coordinate, relative to v. */ - public static void singleClickView(View v, int x, int y) { + public static boolean singleClickView(View v, int x, int y) { int windowXY[] = viewToWindowCoordinates(v, x, y); int windowX = windowXY[0]; int windowY = windowXY[1]; - singleClickInternal(v.getRootView(), windowX, windowY); + return singleClickInternal(v.getRootView(), windowX, windowY); } /** @@ -122,18 +122,18 @@ singleClickView(v, v.getWidth() / 2, v.getHeight() / 2); } - private static void singleClickInternal(View view, float windowX, float windowY) { + private static boolean singleClickInternal(View view, float windowX, float windowY) { long downTime = SystemClock.uptimeMillis(); long eventTime = SystemClock.uptimeMillis(); MotionEvent event = MotionEvent.obtain( downTime, eventTime, MotionEvent.ACTION_DOWN, windowX, windowY, 0); - dispatchTouchEvent(view, event); + if (!dispatchTouchEvent(view, event)) return false; eventTime = SystemClock.uptimeMillis(); event = MotionEvent.obtain( downTime, eventTime, MotionEvent.ACTION_UP, windowX, windowY, 0); - dispatchTouchEvent(view, event); + return dispatchTouchEvent(view, event); } /** @@ -200,12 +200,12 @@ * @param view The view that should receive the event. * @param event The view to be dispatched. */ - private static void dispatchTouchEvent(final View view, final MotionEvent event) { + private static boolean dispatchTouchEvent(final View view, final MotionEvent event) { try { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { + return ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() { @Override - public void run() { - view.dispatchTouchEvent(event); + public Boolean call() { + return view.dispatchTouchEvent(event); } }); } catch (Throwable e) {
diff --git a/content/renderer/media/media_stream_video_capturer_source.cc b/content/renderer/media/media_stream_video_capturer_source.cc index b04383d..d69c6be 100644 --- a/content/renderer/media/media_stream_video_capturer_source.cc +++ b/content/renderer/media/media_stream_video_capturer_source.cc
@@ -233,11 +233,10 @@ // Indicates if we are capturing generated content, e.g. Tab or Desktop. const bool is_content_capture_; - // This is run once to report whether the device was successfully started - // after a call to StartCapture(). + // These two are valid between StartCapture() and StopCapture(). + // |running_call_back_| is run when capture is successfully started, and when + // it is stopped or error happens. RunningCallback running_callback_; - - // This is valid between StartCapture() and StopCapture(). base::Closure stop_capture_cb_; // Placeholder keeping the callback between asynchronous device enumeration @@ -355,7 +354,7 @@ return; switch (state) { case VIDEO_CAPTURE_STATE_STARTED: - base::ResetAndReturn(&running_callback_).Run(true); + running_callback_.Run(true); break; case VIDEO_CAPTURE_STATE_STOPPING:
diff --git a/content/renderer/media/renderer_gpu_video_accelerator_factories.cc b/content/renderer/media/renderer_gpu_video_accelerator_factories.cc index 022d7bf..754c1006 100644 --- a/content/renderer/media/renderer_gpu_video_accelerator_factories.cc +++ b/content/renderer/media/renderer_gpu_video_accelerator_factories.cc
@@ -245,20 +245,20 @@ return found->second; } -media::VideoPixelFormat +media::GpuVideoAcceleratorFactories::OutputFormat RendererGpuVideoAcceleratorFactories::VideoFrameOutputFormat() { DCHECK(task_runner_->BelongsToCurrentThread()); if (CheckContextLost()) - return media::PIXEL_FORMAT_UNKNOWN; + return media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED; cc::ContextProvider::ScopedContextLock lock(context_provider_); auto capabilities = context_provider_->ContextCapabilities(); if (capabilities.image_ycbcr_420v) - return media::PIXEL_FORMAT_NV12; + return media::GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB; if (capabilities.image_ycbcr_422) - return media::PIXEL_FORMAT_UYVY; + return media::GpuVideoAcceleratorFactories::OutputFormat::UYVY; if (capabilities.texture_rg) - return media::PIXEL_FORMAT_I420; - return media::PIXEL_FORMAT_UNKNOWN; + return media::GpuVideoAcceleratorFactories::OutputFormat::NV12_DUAL_GMB; + return media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED; } namespace {
diff --git a/content/renderer/media/renderer_gpu_video_accelerator_factories.h b/content/renderer/media/renderer_gpu_video_accelerator_factories.h index 90ed82c2..4f6a85bf 100644 --- a/content/renderer/media/renderer_gpu_video_accelerator_factories.h +++ b/content/renderer/media/renderer_gpu_video_accelerator_factories.h
@@ -80,7 +80,7 @@ bool ShouldUseGpuMemoryBuffersForVideoFrames() const override; unsigned ImageTextureTarget(gfx::BufferFormat format) override; - media::VideoPixelFormat VideoFrameOutputFormat() override; + OutputFormat VideoFrameOutputFormat() override; std::unique_ptr<media::GpuVideoAcceleratorFactories::ScopedGLContextLock> GetGLContextLock() override; bool CheckContextLost();
diff --git a/content/renderer/media/user_media_client_impl.cc b/content/renderer/media/user_media_client_impl.cc index 3262a4c..d4ea066 100644 --- a/content/renderer/media/user_media_client_impl.cc +++ b/content/renderer/media/user_media_client_impl.cc
@@ -86,6 +86,14 @@ } } } + + if (request.audioConstraints().basic().disableLocalEcho.hasExact()) { + controls->disable_local_echo = + request.audioConstraints().basic().disableLocalEcho.exact(); + } else { + controls->disable_local_echo = + controls->audio.stream_source != kMediaStreamSourceDesktop; + } } if (!request.videoConstraints().isNull()) { const blink::WebMediaTrackConstraintSet& video_basic =
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 348f57d..44af6e03 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -221,11 +221,14 @@ #include "content/renderer/android/app_web_message_port_client.h" #include "content/renderer/java/gin_java_bridge_dispatcher.h" +#include "content/renderer/media/android/media_player_renderer_client_factory.h" #include "content/renderer/media/android/renderer_media_player_manager.h" #include "content/renderer/media/android/renderer_surface_view_manager.h" #include "content/renderer/media/android/stream_texture_factory.h" +#include "content/renderer/media/android/stream_texture_wrapper_impl.h" #include "content/renderer/media/android/webmediaplayer_android.h" #include "media/base/android/media_codec_util.h" +#include "media/mojo/clients/mojo_renderer_factory.h" // nogncheck #include "third_party/WebKit/public/platform/WebFloatPoint.h" #endif @@ -2735,25 +2738,43 @@ base::Unretained(blink::mainThreadIsolate())), initial_cdm, media_surface_manager_, media_observer); + bool use_fallback_path = false; #if defined(OS_ANDROID) - if (!UseWebMediaPlayerImpl(url)) { + use_fallback_path = !UseWebMediaPlayerImpl(url); + + if (use_fallback_path && + !base::FeatureList::IsEnabled(media::kAndroidMediaPlayerRenderer)) { return CreateAndroidWebMediaPlayer(client, encrypted_client, params); } #endif // defined(OS_ANDROID) + std::unique_ptr<media::RendererFactory> media_renderer_factory; + if (use_fallback_path) { +#if defined(OS_ANDROID) + auto mojo_renderer_factory = base::MakeUnique<media::MojoRendererFactory>( + media::MojoRendererFactory::GetGpuFactoriesCB(), + GetRemoteInterfaces()->get()); + + media_renderer_factory = base::MakeUnique<MediaPlayerRendererClientFactory>( + render_thread->compositor_task_runner(), + std::move(mojo_renderer_factory), + base::Bind(&StreamTextureWrapperImpl::Create, + render_thread->GetStreamTexureFactory(), + base::ThreadTaskRunnerHandle::Get())); +#endif // defined(OS_ANDROID) + } else { #if defined(ENABLE_MOJO_RENDERER) - std::unique_ptr<media::RendererFactory> media_renderer_factory( - new media::MojoRendererFactory( - base::Bind(&RenderThreadImpl::GetGpuFactories, - base::Unretained(render_thread)), - GetMediaInterfaceProvider())); + media_renderer_factory = base::MakeUnique<media::MojoRendererFactory>( + base::Bind(&RenderThreadImpl::GetGpuFactories, + base::Unretained(render_thread)), + GetMediaInterfaceProvider()); #else - std::unique_ptr<media::RendererFactory> media_renderer_factory( - new media::DefaultRendererFactory( - media_log, GetDecoderFactory(), - base::Bind(&RenderThreadImpl::GetGpuFactories, - base::Unretained(render_thread)))); + media_renderer_factory = base::MakeUnique<media::DefaultRendererFactory>( + media_log, GetDecoderFactory(), + base::Bind(&RenderThreadImpl::GetGpuFactories, + base::Unretained(render_thread))); #endif + } #if BUILDFLAG(ENABLE_MEDIA_REMOTING) media::RemotingController* remoting_controller_ptr = @@ -2773,13 +2794,13 @@ #if defined(OS_ANDROID) // WMPI_CAST media_player->SetMediaPlayerManager(GetMediaPlayerManager()); media_player->SetDeviceScaleFactor(render_view_->GetDeviceScaleFactor()); + media_player->SetUseFallbackPath(use_fallback_path); #endif // defined(OS_ANDROID) #if BUILDFLAG(ENABLE_MEDIA_REMOTING) remoting_controller_ptr->SetSwitchRendererCallback(base::Bind( &media::WebMediaPlayerImpl::ScheduleRestart, media_player->AsWeakPtr())); #endif - return media_player; } @@ -3578,10 +3599,6 @@ } } - bool sent = Send( - new FrameHostMsg_DidAssignPageId(routing_id_, render_view_->page_id_)); - CHECK(sent); // http://crbug.com/407376 - FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers_, DidCommitProvisionalLoad(frame, is_new_navigation)); FOR_EACH_OBSERVER( @@ -6301,7 +6318,6 @@ media_player_manager_ = new RendererMediaPlayerManager(this); return media_player_manager_; } - #endif // defined(OS_ANDROID) media::MediaPermission* RenderFrameImpl::GetMediaPermission() {
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index 4663a91..23efb1b9 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -644,51 +644,6 @@ EXPECT_EQ(0, memcmp(raw_data, element.data.data(), length)); } -// Check that page ID will be initialized in case of navigation -// that replaces current entry. -TEST_F(RenderViewImplTest, OnBrowserNavigationUpdatePageID) { - // An http url will trigger a resource load so cannot be used here. - CommonNavigationParams common_params; - StartNavigationParams start_params; - RequestNavigationParams request_params; - common_params.url = GURL("data:text/html,<div>Page</div>"); - common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL; - common_params.transition = ui::PAGE_TRANSITION_TYPED; - - // Set up params to emulate a browser side navigation - // that should replace current entry. - common_params.should_replace_current_entry = true; - request_params.page_id = -1; - request_params.nav_entry_id = 1; - request_params.current_history_list_length = 1; - - frame()->Navigate(common_params, start_params, request_params); - ProcessPendingMessages(); - - // Page ID should be initialized. - EXPECT_NE(view_page_id(), -1); - - const IPC::Message* frame_navigate_msg = - render_thread_->sink().GetUniqueMessageMatching( - FrameHostMsg_DidCommitProvisionalLoad::ID); - EXPECT_TRUE(frame_navigate_msg); - - FrameHostMsg_DidCommitProvisionalLoad::Param host_nav_params; - FrameHostMsg_DidCommitProvisionalLoad::Read(frame_navigate_msg, - &host_nav_params); - EXPECT_TRUE(std::get<0>(host_nav_params).page_state.IsValid()); - - const IPC::Message* frame_page_id_msg = - render_thread_->sink().GetUniqueMessageMatching( - FrameHostMsg_DidAssignPageId::ID); - EXPECT_TRUE(frame_page_id_msg); - - FrameHostMsg_DidAssignPageId::Param host_page_id_params; - FrameHostMsg_DidAssignPageId::Read(frame_page_id_msg, &host_page_id_params); - - EXPECT_EQ(std::get<0>(host_page_id_params), view_page_id()); -} - #if defined(OS_ANDROID) TEST_F(RenderViewImplTest, OnNavigationLoadDataWithBaseURL) { CommonNavigationParams common_params; @@ -1020,9 +975,7 @@ ASSERT_TRUE(msg_A); ViewHostMsg_UpdateState::Param param; ViewHostMsg_UpdateState::Read(msg_A, ¶m); - int page_id_A = std::get<0>(param); - PageState state_A = std::get<1>(param); - EXPECT_EQ(1, page_id_A); + PageState state_A = std::get<0>(param); render_thread_->sink().ClearMessages(); // Load page C, which will trigger an UpdateState message for page B. @@ -1034,9 +987,7 @@ ViewHostMsg_UpdateState::ID); ASSERT_TRUE(msg_B); ViewHostMsg_UpdateState::Read(msg_B, ¶m); - int page_id_B = std::get<0>(param); - PageState state_B = std::get<1>(param); - EXPECT_EQ(2, page_id_B); + PageState state_B = std::get<0>(param); EXPECT_NE(state_A, state_B); render_thread_->sink().ClearMessages(); @@ -1049,9 +1000,7 @@ ViewHostMsg_UpdateState::ID); ASSERT_TRUE(msg_C); ViewHostMsg_UpdateState::Read(msg_C, ¶m); - int page_id_C = std::get<0>(param); - PageState state_C = std::get<1>(param); - EXPECT_EQ(3, page_id_C); + PageState state_C = std::get<0>(param); EXPECT_NE(state_B, state_C); render_thread_->sink().ClearMessages(); @@ -1104,9 +1053,7 @@ ViewHostMsg_UpdateState::ID); ASSERT_TRUE(msg); ViewHostMsg_UpdateState::Read(msg, ¶m); - int page_id = std::get<0>(param); - PageState state = std::get<1>(param); - EXPECT_EQ(page_id_C, page_id); + PageState state = std::get<0>(param); EXPECT_NE(state_A, state); EXPECT_NE(state_B, state); EXPECT_EQ(state_C, state);
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 2cd7b96..19562aa 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -1462,7 +1462,7 @@ if (!entry) return; - Send(new ViewHostMsg_UpdateState(GetRoutingID(), page_id_, + Send(new ViewHostMsg_UpdateState(GetRoutingID(), HistoryEntryToPageState(entry))); }
diff --git a/content/test/data/fuzzer_corpus/origin_trial_token_data/24 b/content/test/data/fuzzer_corpus/origin_trial_token_data/24 new file mode 100644 index 0000000..8c374fe --- /dev/null +++ b/content/test/data/fuzzer_corpus/origin_trial_token_data/24
@@ -0,0 +1 @@ +{"feature":"WebBluetooth","isSubdomain":true,origin":"https://example.com:443","expiry":1458766277}
diff --git a/content/test/data/fuzzer_corpus/origin_trial_token_data/25 b/content/test/data/fuzzer_corpus/origin_trial_token_data/25 new file mode 100644 index 0000000..4f77080 --- /dev/null +++ b/content/test/data/fuzzer_corpus/origin_trial_token_data/25
@@ -0,0 +1,6 @@ +{ + "feature": "WebBluetooth", + "isSubdomain": false, + "origin": "https://example.com:443", + "expiry": 1458766277 +}
diff --git a/content/test/data/fuzzer_corpus/origin_trial_token_data/26 b/content/test/data/fuzzer_corpus/origin_trial_token_data/26 new file mode 100644 index 0000000..ea55826a --- /dev/null +++ b/content/test/data/fuzzer_corpus/origin_trial_token_data/26
@@ -0,0 +1 @@ +{"origin":"https://example.com:443","isSubdomain": 1,"something":"else","feature":"WebBluetooth","expiry":1458766277}
diff --git a/content/test/data/fuzzer_corpus/origin_trial_token_data/27 b/content/test/data/fuzzer_corpus/origin_trial_token_data/27 new file mode 100644 index 0000000..4c20906e --- /dev/null +++ b/content/test/data/fuzzer_corpus/origin_trial_token_data/27
@@ -0,0 +1 @@ +{"origin":"https://example.com:443","isSubdomain":"something","feature":"WebBluetooth","expiry":1458766277}
diff --git a/content/test/data/fuzzer_dictionaries/origin_trial_token_fuzzer.dict b/content/test/data/fuzzer_dictionaries/origin_trial_token_fuzzer.dict index 540558f2..83315d6 100644 --- a/content/test/data/fuzzer_dictionaries/origin_trial_token_fuzzer.dict +++ b/content/test/data/fuzzer_dictionaries/origin_trial_token_fuzzer.dict
@@ -3,8 +3,11 @@ # found in the LICENSE file. "\"origin\"" +"\"isSubdomain\"" "\"feature\"" "\"expiry\"" "https://" "example.com" ":443" +"true" +"false"
diff --git a/content/test/data/media/getusermedia.html b/content/test/data/media/getusermedia.html index e045635..e8aac18f 100644 --- a/content/test/data/media/getusermedia.html +++ b/content/test/data/media/getusermedia.html
@@ -42,6 +42,15 @@ failedCallback); } + // Requests getusermedia and expects it to succeed. + function getUserMediaAndExpectSuccess(constraints) { + console.log('Calling getUserMediaAndExpectSuccess.'); + navigator.webkitGetUserMedia( + constraints, + reportTestSuccess, + failedCallback); + } + // Requests getusermedia and expects it to fail. The error name is returned // to the test. function getUserMediaAndExpectFailure(constraints) {
diff --git a/content/test/test_render_view_host.cc b/content/test/test_render_view_host.cc index 06692b20..56ffa6a 100644 --- a/content/test/test_render_view_host.cc +++ b/content/test/test_render_view_host.cc
@@ -307,14 +307,13 @@ } void TestRenderViewHost::TestOnUpdateStateWithFile( - int page_id, const base::FilePath& file_path) { PageState state = PageState::CreateForTesting(GURL("http://www.google.com"), false, "data", &file_path); if (SiteIsolationPolicy::UseSubframeNavigationEntries()) { static_cast<RenderFrameHostImpl*>(GetMainFrame())->OnUpdateState(state); } else { - OnUpdateState(page_id, state); + OnUpdateState(state); } }
diff --git a/content/test/test_render_view_host.h b/content/test/test_render_view_host.h index f8662c3..8b215f61 100644 --- a/content/test/test_render_view_host.h +++ b/content/test/test_render_view_host.h
@@ -197,8 +197,7 @@ void SimulateWasShown() override; WebPreferences TestComputeWebkitPrefs() override; - void TestOnUpdateStateWithFile( - int page_id, const base::FilePath& file_path); + void TestOnUpdateStateWithFile(const base::FilePath& file_path); void TestOnStartDragging(const DropData& drop_data);
diff --git a/dbus/dbus_statistics.cc b/dbus/dbus_statistics.cc index 4bcf7fb..2949c50 100644 --- a/dbus/dbus_statistics.cc +++ b/dbus/dbus_statistics.cc
@@ -4,12 +4,11 @@ #include "dbus/dbus_statistics.h" -#include <memory> -#include <set> +#include <map> +#include <tuple> #include "base/logging.h" #include "base/macros.h" -#include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" @@ -18,43 +17,24 @@ namespace { -// Used to store dbus statistics sorted alphabetically by service, interface, -// then method (using std::string <). -struct Stat { - Stat(const std::string& service, - const std::string& interface, - const std::string& method) - : service(service), - interface(interface), - method(method), - sent_method_calls(0), - received_signals(0), - sent_blocking_method_calls(0) { - } +struct StatKey { std::string service; std::string interface; std::string method; - int sent_method_calls; - int received_signals; - int sent_blocking_method_calls; - - bool Compare(const Stat& other) const { - if (service != other.service) - return service < other.service; - if (interface != other.interface) - return interface < other.interface; - return method < other.method; - } - - struct PtrCompare { - bool operator()(Stat* lhs, Stat* rhs) const { - DCHECK(lhs && rhs); - return lhs->Compare(*rhs); - } - }; }; -typedef std::set<Stat*, Stat::PtrCompare> StatSet; +bool operator<(const StatKey& lhs, const StatKey& rhs) { + return std::tie(lhs.service, lhs.interface, lhs.method) < + std::tie(rhs.service, rhs.interface, rhs.method); +} + +struct StatValue { + int sent_method_calls = 0; + int received_signals = 0; + int sent_blocking_method_calls = 0; +}; + +using StatMap = std::map<StatKey, StatValue>; //------------------------------------------------------------------------------ // DBusStatistics @@ -69,10 +49,9 @@ ~DBusStatistics() { DCHECK_EQ(origin_thread_id_, base::PlatformThread::CurrentId()); - base::STLDeleteContainerPointers(stats_.begin(), stats_.end()); } - // Enum to specify which field in Stat to increment in AddStat + // Enum to specify which field in Stat to increment in AddStat. enum StatType { TYPE_SENT_METHOD_CALLS, TYPE_RECEIVED_SIGNALS, @@ -89,7 +68,7 @@ << base::PlatformThread::CurrentId(); return; } - Stat* stat = GetStat(service, interface, method, true); + StatValue* stat = GetStats(service, interface, method, true); DCHECK(stat); if (type == TYPE_SENT_METHOD_CALLS) ++stat->sent_method_calls; @@ -103,33 +82,35 @@ // Look up the Stat entry in |stats_|. If |add_stat| is true, add a new entry // if one does not already exist. - Stat* GetStat(const std::string& service, - const std::string& interface, - const std::string& method, - bool add_stat) { + StatValue* GetStats(const std::string& service, + const std::string& interface, + const std::string& method, + bool add_stat) { DCHECK_EQ(origin_thread_id_, base::PlatformThread::CurrentId()); - std::unique_ptr<Stat> stat(new Stat(service, interface, method)); - StatSet::iterator found = stats_.find(stat.get()); - if (found != stats_.end()) - return *found; + + StatKey key = {service, interface, method}; + auto it = stats_.find(key); + if (it != stats_.end()) + return &(it->second); + if (!add_stat) - return NULL; - found = stats_.insert(stat.release()).first; - return *found; + return nullptr; + + return &(stats_[key]); } - StatSet& stats() { return stats_; } + StatMap& stats() { return stats_; } base::Time start_time() { return start_time_; } private: - StatSet stats_; + StatMap stats_; base::Time start_time_; base::PlatformThreadId origin_thread_id_; DISALLOW_COPY_AND_ASSIGN(DBusStatistics); }; -DBusStatistics* g_dbus_statistics = NULL; +DBusStatistics* g_dbus_statistics = nullptr; } // namespace @@ -145,7 +126,7 @@ void Shutdown() { delete g_dbus_statistics; - g_dbus_statistics = NULL; + g_dbus_statistics = nullptr; } void AddSentMethodCall(const std::string& service, @@ -182,7 +163,7 @@ if (!g_dbus_statistics) return "DBusStatistics not initialized."; - const StatSet& stats = g_dbus_statistics->stats(); + const StatMap& stats = g_dbus_statistics->stats(); if (stats.empty()) return "No DBus calls."; @@ -193,19 +174,21 @@ std::string result; int sent = 0, received = 0, sent_blocking = 0; // Stats are stored in order by service, then interface, then method. - for (StatSet::const_iterator iter = stats.begin(); iter != stats.end(); ) { - StatSet::const_iterator cur_iter = iter; - StatSet::const_iterator next_iter = ++iter; - const Stat* stat = *cur_iter; - sent += stat->sent_method_calls; - received += stat->received_signals; - sent_blocking += stat->sent_blocking_method_calls; + for (auto iter = stats.begin(); iter != stats.end();) { + auto cur_iter = iter; + auto next_iter = ++iter; + const StatKey& stat_key = cur_iter->first; + const StatValue& stat = cur_iter->second; + sent += stat.sent_method_calls; + received += stat.received_signals; + sent_blocking += stat.sent_blocking_method_calls; // If this is not the last stat, and if the next stat matches the current // stat, continue. if (next_iter != stats.end() && - (*next_iter)->service == stat->service && - (show < SHOW_INTERFACE || (*next_iter)->interface == stat->interface) && - (show < SHOW_METHOD || (*next_iter)->method == stat->method)) + next_iter->first.service == stat_key.service && + (show < SHOW_INTERFACE || + next_iter->first.interface == stat_key.interface) && + (show < SHOW_METHOD || next_iter->first.method == stat_key.method)) continue; if (!sent && !received && !sent_blocking) @@ -214,12 +197,12 @@ // Add a line to the result and clear the counts. std::string line; if (show == SHOW_SERVICE) { - line += stat->service; + line += stat_key.service; } else { // The interface usually includes the service so don't show both. - line += stat->interface; + line += stat_key.interface; if (show >= SHOW_METHOD) - line += "." + stat->method; + line += "." + stat_key.method; } line += base::StringPrintf(":"); if (sent_blocking) { @@ -269,7 +252,8 @@ int* blocking) { if (!g_dbus_statistics) return false; - Stat* stat = g_dbus_statistics->GetStat(service, interface, method, false); + StatValue* stat = + g_dbus_statistics->GetStats(service, interface, method, false); if (!stat) return false; *sent = stat->sent_method_calls;
diff --git a/device/BUILD.gn b/device/BUILD.gn index 3ebf59a..5cb0349 100644 --- a/device/BUILD.gn +++ b/device/BUILD.gn
@@ -139,8 +139,8 @@ "usb/webusb_descriptors_unittest.cc", ] deps += [ - "//device/core", - "//device/core:mocks", + "//device/base", + "//device/base:mocks", "//device/usb", "//device/usb:test_support", "//device/usb/mojo",
diff --git a/device/core/BUILD.gn b/device/base/BUILD.gn similarity index 88% rename from device/core/BUILD.gn rename to device/base/BUILD.gn index f4c8e18..6240ae9 100644 --- a/device/core/BUILD.gn +++ b/device/base/BUILD.gn
@@ -4,8 +4,8 @@ import("//build/config/features.gni") -component("core") { - output_name = "device_core" +component("base") { + output_name = "device_base" sources = [ "device_client.cc", @@ -16,7 +16,7 @@ "device_monitor_win.h", ] - defines = [ "DEVICE_CORE_IMPLEMENTATION" ] + defines = [ "DEVICE_BASE_IMPLEMENTATION" ] deps = [] @@ -47,7 +47,7 @@ ] deps = [ - ":core", + ":base", "//device/hid:mocks", "//device/usb:test_support", ]
diff --git a/device/base/device_base_export.h b/device/base/device_base_export.h new file mode 100644 index 0000000..f896ea85 --- /dev/null +++ b/device/base/device_base_export.h
@@ -0,0 +1,28 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BASE_DEVICE_BASE_EXPORT_H_ +#define DEVICE_BASE_DEVICE_BASE_EXPORT_H_ + +#if defined(COMPONENT_BUILD) && defined(WIN32) + +#if defined(DEVICE_BASE_IMPLEMENTATION) +#define DEVICE_BASE_EXPORT __declspec(dllexport) +#else +#define DEVICE_BASE_EXPORT __declspec(dllimport) +#endif + +#elif defined(COMPONENT_BUILD) && !defined(WIN32) + +#if defined(DEVICE_BASE_IMPLEMENTATION) +#define DEVICE_BASE_EXPORT __attribute__((visibility("default"))) +#else +#define DEVICE_BASE_EXPORT +#endif + +#else +#define DEVICE_BASE_EXPORT +#endif + +#endif // DEVICE_BASE_DEVICE_BASE_EXPORT_H_
diff --git a/device/core/device_client.cc b/device/base/device_client.cc similarity index 95% rename from device/core/device_client.cc rename to device/base/device_client.cc index 50b015e..91707e3 100644 --- a/device/core/device_client.cc +++ b/device/base/device_client.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 "device/core/device_client.h" +#include "device/base/device_client.h" #include "base/logging.h"
diff --git a/device/core/device_client.h b/device/base/device_client.h similarity index 82% rename from device/core/device_client.h rename to device/base/device_client.h index 9fdc7f1..c1421fde 100644 --- a/device/core/device_client.h +++ b/device/base/device_client.h
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef DEVICE_CORE_DEVICE_CLIENT_H_ -#define DEVICE_CORE_DEVICE_CLIENT_H_ +#ifndef DEVICE_BASE_DEVICE_CLIENT_H_ +#define DEVICE_BASE_DEVICE_CLIENT_H_ #include "base/macros.h" -#include "device/core/device_core_export.h" +#include "device/base/device_base_export.h" namespace device { @@ -16,7 +16,7 @@ // Interface used by consumers of //device APIs to get pointers to the service // singletons appropriate for a given embedding application. For an example see // //chrome/browser/chrome_device_client.h. -class DEVICE_CORE_EXPORT DeviceClient { +class DEVICE_BASE_EXPORT DeviceClient { public: // Construction sets the single instance. DeviceClient(); @@ -39,4 +39,4 @@ } // namespace device -#endif // DEVICE_CORE_DEVICE_CLIENT_H_ +#endif // DEVICE_BASE_DEVICE_CLIENT_H_
diff --git a/device/core/device_info_query_win.cc b/device/base/device_info_query_win.cc similarity index 97% rename from device/core/device_info_query_win.cc rename to device/base/device_info_query_win.cc index 2d8864b7..3ff6f5ea 100644 --- a/device/core/device_info_query_win.cc +++ b/device/base/device_info_query_win.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 "device/core/device_info_query_win.h" +#include "device/base/device_info_query_win.h" #include <stddef.h> #include <string.h>
diff --git a/device/core/device_info_query_win.h b/device/base/device_info_query_win.h similarity index 85% rename from device/core/device_info_query_win.h rename to device/base/device_info_query_win.h index 2e399e49..17ee13b 100644 --- a/device/core/device_info_query_win.h +++ b/device/base/device_info_query_win.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 DEVICE_CORE_DEVICE_INFO_QUERY_WIN_H_ -#define DEVICE_CORE_DEVICE_INFO_QUERY_WIN_H_ +#ifndef DEVICE_BASE_DEVICE_INFO_QUERY_WIN_H_ +#define DEVICE_BASE_DEVICE_INFO_QUERY_WIN_H_ #include <windows.h> #include <setupapi.h> @@ -11,14 +11,14 @@ #include <string> #include "base/macros.h" -#include "device/core/device_core_export.h" +#include "device/base/device_base_export.h" namespace device { // Wraps HDEVINFO and SP_DEVINFO_DATA into a class that can automatically // release them. Provides interfaces that can add a device using its // device path, get device info and get device string property. -class DEVICE_CORE_EXPORT DeviceInfoQueryWin { +class DEVICE_BASE_EXPORT DeviceInfoQueryWin { public: DeviceInfoQueryWin(); ~DeviceInfoQueryWin(); @@ -46,4 +46,4 @@ } // namespace device -#endif // DEVICE_CORE_DEVICE_INFO_QUERY_WIN_H_ +#endif // DEVICE_BASE_DEVICE_INFO_QUERY_WIN_H_
diff --git a/device/core/device_monitor_linux.cc b/device/base/device_monitor_linux.cc similarity index 90% rename from device/core/device_monitor_linux.cc rename to device/base/device_monitor_linux.cc index 73841611..cc64870 100644 --- a/device/core/device_monitor_linux.cc +++ b/device/base/device_monitor_linux.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 "device/core/device_monitor_linux.h" +#include "device/base/device_monitor_linux.h" #include <memory> @@ -111,7 +111,8 @@ void DeviceMonitorLinux::WillDestroyCurrentMessageLoop() { DCHECK(thread_checker_.CalledOnValidThread()); - FOR_EACH_OBSERVER(Observer, observers_, WillDestroyMonitorMessageLoop()); + for (auto& observer : observers_) + observer.WillDestroyMonitorMessageLoop(); g_device_monitor_linux_ptr.Get().reset(nullptr); } @@ -129,10 +130,13 @@ return; std::string action(udev_device_get_action(device.get())); - if (action == kUdevActionAdd) - FOR_EACH_OBSERVER(Observer, observers_, OnDeviceAdded(device.get())); - else if (action == kUdevActionRemove) - FOR_EACH_OBSERVER(Observer, observers_, OnDeviceRemoved(device.get())); + if (action == kUdevActionAdd) { + for (auto& observer : observers_) + observer.OnDeviceAdded(device.get()); + } else if (action == kUdevActionRemove) { + for (auto& observer : observers_) + observer.OnDeviceRemoved(device.get()); + } } } // namespace device
diff --git a/device/core/device_monitor_linux.h b/device/base/device_monitor_linux.h similarity index 89% rename from device/core/device_monitor_linux.h rename to device/base/device_monitor_linux.h index 6cc64e7..72b740bad 100644 --- a/device/core/device_monitor_linux.h +++ b/device/base/device_monitor_linux.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 DEVICE_HID_DEVICE_MONITOR_LINUX_H_ -#define DEVICE_HID_DEVICE_MONITOR_LINUX_H_ +#ifndef DEVICE_BASE_DEVICE_MONITOR_LINUX_H_ +#define DEVICE_BASE_DEVICE_MONITOR_LINUX_H_ #include <memory> #include <string> @@ -14,7 +14,7 @@ #include "base/message_loop/message_loop.h" #include "base/observer_list.h" #include "base/threading/thread_checker.h" -#include "device/core/device_core_export.h" +#include "device/base/device_base_export.h" #include "device/udev_linux/scoped_udev.h" struct udev_device; @@ -23,7 +23,7 @@ // This class listends for notifications from libudev about // connected/disconnected devices. This class is *NOT* thread-safe. -class DEVICE_CORE_EXPORT DeviceMonitorLinux +class DEVICE_BASE_EXPORT DeviceMonitorLinux : public base::MessageLoop::DestructionObserver { public: typedef base::Callback<void(udev_device* device)> EnumerateCallback; @@ -71,4 +71,4 @@ } // namespace device -#endif // DEVICE_HID_DEVICE_MONITOR_LINUX_H_ +#endif // DEVICE_BASE_DEVICE_MONITOR_LINUX_H_
diff --git a/device/core/device_monitor_win.cc b/device/base/device_monitor_win.cc similarity index 91% rename from device/core/device_monitor_win.cc rename to device/base/device_monitor_win.cc index adeb3fa..39fe747 100644 --- a/device/core/device_monitor_win.cc +++ b/device/base/device_monitor_win.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 "device/core/device_monitor_win.h" +#include "device/base/device_monitor_win.h" #include <dbt.h> #include <windows.h> @@ -45,8 +45,8 @@ g_message_window = new DeviceMonitorMessageWindow(); if (g_message_window->Init()) { base::AtExitManager::RegisterTask( - base::Bind(&base::DeletePointer<DeviceMonitorMessageWindow>, - base::Unretained(g_message_window))); + base::Bind(&base::DeletePointer<DeviceMonitorMessageWindow>, + base::Unretained(g_message_window))); } else { delete g_message_window; g_message_window = nullptr; @@ -70,8 +70,7 @@ friend void base::DeletePointer<DeviceMonitorMessageWindow>( DeviceMonitorMessageWindow* message_window); - DeviceMonitorMessageWindow() { - } + DeviceMonitorMessageWindow() {} ~DeviceMonitorMessageWindow() { if (notify_handle_) { @@ -157,8 +156,7 @@ void DeviceMonitorWin::Observer::OnDeviceRemoved( const GUID& class_guid, - const std::string& device_path) { -} + const std::string& device_path) {} // static DeviceMonitorWin* DeviceMonitorWin::GetForDeviceInterface( @@ -181,8 +179,7 @@ return nullptr; } -DeviceMonitorWin::~DeviceMonitorWin() { -} +DeviceMonitorWin::~DeviceMonitorWin() {} void DeviceMonitorWin::AddObserver(Observer* observer) { observer_list_.AddObserver(observer); @@ -192,19 +189,18 @@ observer_list_.RemoveObserver(observer); } -DeviceMonitorWin::DeviceMonitorWin() { -} +DeviceMonitorWin::DeviceMonitorWin() {} void DeviceMonitorWin::NotifyDeviceAdded(const GUID& class_guid, const std::string& device_path) { - FOR_EACH_OBSERVER(Observer, observer_list_, - OnDeviceAdded(class_guid, device_path)); + for (auto& observer : observer_list_) + observer.OnDeviceAdded(class_guid, device_path); } void DeviceMonitorWin::NotifyDeviceRemoved(const GUID& class_guid, const std::string& device_path) { - FOR_EACH_OBSERVER(Observer, observer_list_, - OnDeviceRemoved(class_guid, device_path)); + for (auto& observer : observer_list_) + observer.OnDeviceRemoved(class_guid, device_path); } } // namespace device
diff --git a/device/core/device_monitor_win.h b/device/base/device_monitor_win.h similarity index 82% rename from device/core/device_monitor_win.h rename to device/base/device_monitor_win.h index 36600e4..0370c79 100644 --- a/device/core/device_monitor_win.h +++ b/device/base/device_monitor_win.h
@@ -2,21 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef DEVICE_CORE_DEVICE_MONITOR_WIN_H_ -#define DEVICE_CORE_DEVICE_MONITOR_WIN_H_ +#ifndef DEVICE_BASE_DEVICE_MONITOR_WIN_H_ +#define DEVICE_BASE_DEVICE_MONITOR_WIN_H_ #include <windows.h> #include "base/observer_list.h" -#include "device/core/device_core_export.h" +#include "device/base/device_base_export.h" namespace device { // Use an instance of this class to observe devices being added and removed // from the system, matched by device interface GUID. -class DEVICE_CORE_EXPORT DeviceMonitorWin { +class DEVICE_BASE_EXPORT DeviceMonitorWin { public: - class DEVICE_CORE_EXPORT Observer { + class DEVICE_BASE_EXPORT Observer { public: virtual void OnDeviceAdded(const GUID& class_guid, const std::string& device_path); @@ -47,4 +47,4 @@ } // namespace device -#endif // DEVICE_CORE_DEVICE_MONITOR_WIN_H_ +#endif // DEVICE_BASE_DEVICE_MONITOR_WIN_H_
diff --git a/device/core/mock_device_client.cc b/device/base/mock_device_client.cc similarity index 94% rename from device/core/mock_device_client.cc rename to device/base/mock_device_client.cc index 8e82c37..1c75231 100644 --- a/device/core/mock_device_client.cc +++ b/device/base/mock_device_client.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 "device/core/mock_device_client.h" +#include "device/base/mock_device_client.h" #include "device/hid/mock_hid_service.h" #include "device/usb/mock_usb_service.h"
diff --git a/device/core/mock_device_client.h b/device/base/mock_device_client.h similarity index 81% rename from device/core/mock_device_client.h rename to device/base/mock_device_client.h index 810b8ff..04fbd16 100644 --- a/device/core/mock_device_client.h +++ b/device/base/mock_device_client.h
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef DEVICE_CORE_MOCK_DEVICE_CLIENT_H_ -#define DEVICE_CORE_MOCK_DEVICE_CLIENT_H_ +#ifndef DEVICE_BASE_MOCK_DEVICE_CLIENT_H_ +#define DEVICE_BASE_MOCK_DEVICE_CLIENT_H_ #include <memory> -#include "device/core/device_client.h" +#include "device/base/device_client.h" namespace device { @@ -36,4 +36,4 @@ } // namespace device -#endif // DEVICE_CORE_MOCK_DEVICE_CLIENT_H_ +#endif // DEVICE_BASE_MOCK_DEVICE_CLIENT_H_
diff --git a/device/base/synchronization/one_writer_seqlock.cc b/device/base/synchronization/one_writer_seqlock.cc index 2791e8e..7b855cf 100644 --- a/device/base/synchronization/one_writer_seqlock.cc +++ b/device/base/synchronization/one_writer_seqlock.cc
@@ -8,7 +8,7 @@ OneWriterSeqLock::OneWriterSeqLock() : sequence_(0) {} -base::subtle::Atomic32 OneWriterSeqLock::ReadBegin() { +base::subtle::Atomic32 OneWriterSeqLock::ReadBegin() const { base::subtle::Atomic32 version; for (;;) { version = base::subtle::NoBarrier_Load(&sequence_); @@ -24,7 +24,7 @@ return version; } -bool OneWriterSeqLock::ReadRetry(base::subtle::Atomic32 version) { +bool OneWriterSeqLock::ReadRetry(base::subtle::Atomic32 version) const { // If the sequence number was updated then a read should be re-attempted. // -- Load fence, read membarrier return base::subtle::Release_Load(&sequence_) != version;
diff --git a/device/base/synchronization/one_writer_seqlock.h b/device/base/synchronization/one_writer_seqlock.h index a300fe58..29db0f1 100644 --- a/device/base/synchronization/one_writer_seqlock.h +++ b/device/base/synchronization/one_writer_seqlock.h
@@ -31,8 +31,8 @@ class OneWriterSeqLock { public: OneWriterSeqLock(); - base::subtle::Atomic32 ReadBegin(); - bool ReadRetry(base::subtle::Atomic32 version); + base::subtle::Atomic32 ReadBegin() const; + bool ReadRetry(base::subtle::Atomic32 version) const; void WriteBegin(); void WriteEnd();
diff --git a/device/bluetooth/BUILD.gn b/device/bluetooth/BUILD.gn index 0f33ee1..890d444 100644 --- a/device/bluetooth/BUILD.gn +++ b/device/bluetooth/BUILD.gn
@@ -26,6 +26,8 @@ "adapter.h", "adapter_factory.cc", "adapter_factory.h", + "device.cc", + "device.h", ] public_deps = [
diff --git a/device/bluetooth/adapter.cc b/device/bluetooth/adapter.cc index 2352f23..564315e 100644 --- a/device/bluetooth/adapter.cc +++ b/device/bluetooth/adapter.cc
@@ -6,10 +6,8 @@ #include <utility> #include <vector> -#include "base/memory/ptr_util.h" -#include "base/strings/utf_string_conversions.h" #include "device/bluetooth/adapter.h" -#include "mojo/public/cpp/bindings/string.h" +#include "device/bluetooth/device.h" #include "mojo/public/cpp/bindings/strong_binding.h" namespace bluetooth { @@ -36,11 +34,20 @@ callback.Run(std::move(adapter_info)); } +void Adapter::GetDevice(const std::string& address, + const GetDeviceCallback& callback) { + mojom::DevicePtr device_ptr; + mojo::MakeStrongBinding(base::MakeUnique<Device>(address, adapter_), + mojo::GetProxy(&device_ptr)); + callback.Run(std::move(device_ptr)); +} + void Adapter::GetDevices(const GetDevicesCallback& callback) { std::vector<mojom::DeviceInfoPtr> devices; for (const device::BluetoothDevice* device : adapter_->GetDevices()) { - mojom::DeviceInfoPtr device_info = ConstructDeviceInfoStruct(device); + mojom::DeviceInfoPtr device_info = + Device::ConstructDeviceInfoStruct(device); devices.push_back(std::move(device_info)); } @@ -54,7 +61,7 @@ void Adapter::DeviceAdded(device::BluetoothAdapter* adapter, device::BluetoothDevice* device) { if (client_) { - auto device_info = ConstructDeviceInfoStruct(device); + auto device_info = Device::ConstructDeviceInfoStruct(device); client_->DeviceAdded(std::move(device_info)); } } @@ -62,23 +69,9 @@ void Adapter::DeviceRemoved(device::BluetoothAdapter* adapter, device::BluetoothDevice* device) { if (client_) { - auto device_info = ConstructDeviceInfoStruct(device); + auto device_info = Device::ConstructDeviceInfoStruct(device); client_->DeviceRemoved(std::move(device_info)); } } -// static -mojom::DeviceInfoPtr Adapter::ConstructDeviceInfoStruct( - const device::BluetoothDevice* device) { - mojom::DeviceInfoPtr device_info = mojom::DeviceInfo::New(); - - device_info->name = device->GetName(); - device_info->name_for_display = - base::UTF16ToUTF8(device->GetNameForDisplay()); - device_info->id = device->GetIdentifier(); - device_info->address = device->GetAddress(); - - return device_info; -} - } // namespace bluetooth
diff --git a/device/bluetooth/adapter.h b/device/bluetooth/adapter.h index ea034afb..b7a561f 100644 --- a/device/bluetooth/adapter.h +++ b/device/bluetooth/adapter.h
@@ -5,10 +5,13 @@ #ifndef DEVICE_BLUETOOTH_ADAPTER_H_ #define DEVICE_BLUETOOTH_ADAPTER_H_ +#include <string> + #include "base/macros.h" +#include "base/memory/ref_counted.h" #include "device/bluetooth/bluetooth_adapter.h" -#include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/public/interfaces/adapter.mojom.h" +#include "device/bluetooth/public/interfaces/device.mojom.h" namespace bluetooth { @@ -24,6 +27,8 @@ // mojom::Adapter overrides: void GetInfo(const GetInfoCallback& callback) override; + void GetDevice(const std::string& address, + const GetDeviceCallback& callback) override; void GetDevices(const GetDevicesCallback& callback) override; void SetClient(mojom::AdapterClientPtr client) override; @@ -34,10 +39,6 @@ device::BluetoothDevice* device) override; private: - // Creates a mojom::DeviceInfo using info from the given |device|. - static mojom::DeviceInfoPtr ConstructDeviceInfoStruct( - const device::BluetoothDevice* device); - // The current Bluetooth adapter. scoped_refptr<device::BluetoothAdapter> adapter_;
diff --git a/device/bluetooth/device.cc b/device/bluetooth/device.cc new file mode 100644 index 0000000..6ebc34c --- /dev/null +++ b/device/bluetooth/device.cc
@@ -0,0 +1,42 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <utility> + +#include "base/strings/utf_string_conversions.h" +#include "device/bluetooth/device.h" +#include "mojo/public/cpp/bindings/strong_binding.h" + +namespace bluetooth { + +Device::Device(const std::string& address, + scoped_refptr<device::BluetoothAdapter> adapter) + : address_(address), adapter_(std::move(adapter)) {} + +Device::~Device() {} + +// static +mojom::DeviceInfoPtr Device::ConstructDeviceInfoStruct( + const device::BluetoothDevice* device) { + mojom::DeviceInfoPtr device_info = mojom::DeviceInfo::New(); + + device_info->name = device->GetName(); + device_info->name_for_display = + base::UTF16ToUTF8(device->GetNameForDisplay()); + device_info->address = device->GetAddress(); + + return device_info; +} + +void Device::GetInfo(const GetInfoCallback& callback) { + device::BluetoothDevice* device = adapter_->GetDevice(address_); + if (device) { + mojom::DeviceInfoPtr device_info = ConstructDeviceInfoStruct(device); + callback.Run(std::move(device_info)); + } else { + callback.Run(nullptr); + } +} + +} // namespace bluetooth
diff --git a/device/bluetooth/device.h b/device/bluetooth/device.h new file mode 100644 index 0000000..c82439e6 --- /dev/null +++ b/device/bluetooth/device.h
@@ -0,0 +1,47 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_DEVICE_H_ +#define DEVICE_BLUETOOTH_DEVICE_H_ + +#include <string> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "device/bluetooth/bluetooth_adapter.h" +#include "device/bluetooth/bluetooth_device.h" +#include "device/bluetooth/public/interfaces/device.mojom.h" + +namespace bluetooth { + +// Implementation of Mojo Device located in +// device/bluetooth/public/interfaces/device.mojom. +// It handles requests to interact with Bluetooth Device. +// Uses the platform abstraction of device/bluetooth. +class Device : public mojom::Device { + public: + Device(const std::string& address, + scoped_refptr<device::BluetoothAdapter> adapter); + ~Device() override; + + // Creates a mojom::DeviceInfo using info from the given |device|. + static mojom::DeviceInfoPtr ConstructDeviceInfoStruct( + const device::BluetoothDevice* device); + + // mojom::Device overrides: + void GetInfo(const GetInfoCallback& callback) override; + + private: + // The address of the Bluetooth device. + std::string address_; + + // The current BluetoothAdapter. + scoped_refptr<device::BluetoothAdapter> adapter_; + + DISALLOW_COPY_AND_ASSIGN(Device); +}; + +} // namespace bluetooth + +#endif // DEVICE_BLUETOOTH_DEVICE_H_
diff --git a/device/bluetooth/public/interfaces/BUILD.gn b/device/bluetooth/public/interfaces/BUILD.gn index c9105e0..afb2b6d 100644 --- a/device/bluetooth/public/interfaces/BUILD.gn +++ b/device/bluetooth/public/interfaces/BUILD.gn
@@ -15,6 +15,7 @@ mojom("experimental_interfaces") { sources = [ "adapter.mojom", + "device.mojom", ] visibility = [
diff --git a/device/bluetooth/public/interfaces/adapter.mojom b/device/bluetooth/public/interfaces/adapter.mojom index 0ac42f5..959c8e3 100644 --- a/device/bluetooth/public/interfaces/adapter.mojom +++ b/device/bluetooth/public/interfaces/adapter.mojom
@@ -4,6 +4,8 @@ module bluetooth.mojom; +import "device/bluetooth/public/interfaces/device.mojom"; + struct AdapterInfo { string address; string name; @@ -14,17 +16,13 @@ bool discovering; }; -struct DeviceInfo { - string? name; - string name_for_display; - string id; - string address; -}; - interface Adapter { // Gets basic information about the adapter. GetInfo() => (AdapterInfo info); + // Gets the Device service for the device at the given address. + GetDevice(string address) => (Device? device); + // Retrieves the list of the devices known by the adapter including Connected // Devices, GATT Connected Devices, Paired Devices and Devices discovered // during a classic or low-energy scan. @@ -45,4 +43,4 @@ interface AdapterFactory { // Gets an Adapter interface. Returns null if Bluetooth is not supported. GetAdapter() => (Adapter? adapter); -}; \ No newline at end of file +};
diff --git a/device/bluetooth/public/interfaces/device.mojom b/device/bluetooth/public/interfaces/device.mojom new file mode 100644 index 0000000..b629bab --- /dev/null +++ b/device/bluetooth/public/interfaces/device.mojom
@@ -0,0 +1,17 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module bluetooth.mojom; + +struct DeviceInfo { + string? name; + string name_for_display; + string address; +}; + +interface Device { + // Gets basic information about the device. Returns null, if no device is + // available. + GetInfo() => (DeviceInfo? info); +};
diff --git a/device/core/device_core_export.h b/device/core/device_core_export.h deleted file mode 100644 index 6f1cddb..0000000 --- a/device/core/device_core_export.h +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef DEVICE_CORE_DEVICE_CORE_EXPORT_H_ -#define DEVICE_CORE_DEVICE_CORE_EXPORT_H_ - -#if defined(COMPONENT_BUILD) && defined(WIN32) - -#if defined(DEVICE_CORE_IMPLEMENTATION) -#define DEVICE_CORE_EXPORT __declspec(dllexport) -#else -#define DEVICE_CORE_EXPORT __declspec(dllimport) -#endif - -#elif defined(COMPONENT_BUILD) && !defined(WIN32) - -#if defined(DEVICE_CORE_IMPLEMENTATION) -#define DEVICE_CORE_EXPORT __attribute__((visibility("default"))) -#else -#define DEVICE_CORE_EXPORT -#endif - -#else -#define DEVICE_CORE_EXPORT -#endif - -#endif // DEVICE_CORE_DEVICE_CORE_EXPORT_H_
diff --git a/device/generic_sensor/public/cpp/sensor_reading.h b/device/generic_sensor/public/cpp/sensor_reading.h index 6d0a42f..be19708 100644 --- a/device/generic_sensor/public/cpp/sensor_reading.h +++ b/device/generic_sensor/public/cpp/sensor_reading.h
@@ -24,6 +24,8 @@ return *this; } Data& value() { return storage_.value; } + const Data& value() const { return storage_.value; } + operator Data() const { return storage_.value; } private:
diff --git a/device/hid/BUILD.gn b/device/hid/BUILD.gn index 39a8839..6a958172 100644 --- a/device/hid/BUILD.gn +++ b/device/hid/BUILD.gn
@@ -40,7 +40,7 @@ deps = [ "//base", "//components/device_event_log", - "//device/core", + "//device/base", "//net", ]
diff --git a/device/hid/hid_service_linux.cc b/device/hid/hid_service_linux.cc index 848d1f1..c61ae4ed 100644 --- a/device/hid/hid_service_linux.cc +++ b/device/hid/hid_service_linux.cc
@@ -25,7 +25,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "components/device_event_log/device_event_log.h" -#include "device/core/device_monitor_linux.h" +#include "device/base/device_monitor_linux.h" #include "device/hid/hid_connection_linux.h" #include "device/hid/hid_device_info_linux.h" #include "device/udev_linux/scoped_udev.h"
diff --git a/device/hid/hid_service_win.h b/device/hid/hid_service_win.h index 94bb55c..b2219322 100644 --- a/device/hid/hid_service_win.h +++ b/device/hid/hid_service_win.h
@@ -19,7 +19,7 @@ #include "base/memory/weak_ptr.h" #include "base/scoped_observer.h" #include "base/win/scoped_handle.h" -#include "device/core/device_monitor_win.h" +#include "device/base/device_monitor_win.h" #include "device/hid/hid_device_info.h" #include "device/hid/hid_service.h"
diff --git a/device/hid/input_service_linux.cc b/device/hid/input_service_linux.cc index 4df2cb5..75eb352 100644 --- a/device/hid/input_service_linux.cc +++ b/device/hid/input_service_linux.cc
@@ -14,7 +14,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/threading/thread_restrictions.h" -#include "device/core/device_monitor_linux.h" +#include "device/base/device_monitor_linux.h" #include "device/udev_linux/udev.h" namespace device {
diff --git a/device/serial/BUILD.gn b/device/serial/BUILD.gn index 9679a65d..3fd7eb5 100644 --- a/device/serial/BUILD.gn +++ b/device/serial/BUILD.gn
@@ -43,7 +43,7 @@ public_deps = [ ":serial_mojo", "//base", - "//device/core", + "//device/base", ] deps = [
diff --git a/device/serial/serial_io_handler_win.cc b/device/serial/serial_io_handler_win.cc index 1df4c36..aaf8dac 100644 --- a/device/serial/serial_io_handler_win.cc +++ b/device/serial/serial_io_handler_win.cc
@@ -11,8 +11,8 @@ #include "base/macros.h" #include "base/scoped_observer.h" #include "base/threading/thread_checker.h" -#include "device/core/device_info_query_win.h" -#include "device/core/device_monitor_win.h" +#include "device/base/device_info_query_win.h" +#include "device/base/device_monitor_win.h" #include "third_party/re2/src/re2/re2.h" namespace device {
diff --git a/device/test/test_device_client.h b/device/test/test_device_client.h index d4cd627..16275ad3 100644 --- a/device/test/test_device_client.h +++ b/device/test/test_device_client.h
@@ -5,7 +5,7 @@ #include <memory> #include "base/memory/ref_counted.h" -#include "device/core/device_client.h" +#include "device/base/device_client.h" namespace base { class SingleThreadTaskRunner;
diff --git a/device/test/usb_test_gadget_impl.cc b/device/test/usb_test_gadget_impl.cc index 5142d32..ddb79c4 100644 --- a/device/test/usb_test_gadget_impl.cc +++ b/device/test/usb_test_gadget_impl.cc
@@ -27,7 +27,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" -#include "device/core/device_client.h" +#include "device/base/device_client.h" #include "device/test/usb_test_gadget.h" #include "device/usb/usb_device.h" #include "device/usb/usb_device_handle.h"
diff --git a/device/usb/BUILD.gn b/device/usb/BUILD.gn index ce1fe655..f87aef46 100644 --- a/device/usb/BUILD.gn +++ b/device/usb/BUILD.gn
@@ -54,7 +54,7 @@ "//base", "//base/third_party/dynamic_annotations", "//components/device_event_log", - "//device/core", + "//device/base", "//net", ]
diff --git a/device/usb/mojo/BUILD.gn b/device/usb/mojo/BUILD.gn index 1a45f386..25e916b 100644 --- a/device/usb/mojo/BUILD.gn +++ b/device/usb/mojo/BUILD.gn
@@ -15,7 +15,7 @@ ] deps = [ - "//device/core", + "//device/base", "//device/usb", "//device/usb/public/interfaces", "//mojo/common",
diff --git a/device/usb/mojo/device_manager_impl.cc b/device/usb/mojo/device_manager_impl.cc index 767d633..86d4f29 100644 --- a/device/usb/mojo/device_manager_impl.cc +++ b/device/usb/mojo/device_manager_impl.cc
@@ -10,7 +10,7 @@ #include <utility> #include "base/bind.h" -#include "device/core/device_client.h" +#include "device/base/device_client.h" #include "device/usb/mojo/device_impl.h" #include "device/usb/mojo/permission_provider.h" #include "device/usb/mojo/type_converters.h"
diff --git a/device/usb/mojo/device_manager_impl_unittest.cc b/device/usb/mojo/device_manager_impl_unittest.cc index 611237d..c0bd627e 100644 --- a/device/usb/mojo/device_manager_impl_unittest.cc +++ b/device/usb/mojo/device_manager_impl_unittest.cc
@@ -17,7 +17,7 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/threading/thread_task_runner_handle.h" -#include "device/core/mock_device_client.h" +#include "device/base/mock_device_client.h" #include "device/usb/mock_usb_device.h" #include "device/usb/mock_usb_device_handle.h" #include "device/usb/mock_usb_service.h"
diff --git a/device/usb/usb_service_impl.cc b/device/usb/usb_service_impl.cc index 7a23bff..083298d 100644 --- a/device/usb/usb_service_impl.cc +++ b/device/usb/usb_service_impl.cc
@@ -33,7 +33,7 @@ #include <usbiodef.h> #include "base/strings/string_util.h" -#include "device/core/device_info_query_win.h" +#include "device/base/device_info_query_win.h" #endif // OS_WIN using net::IOBufferWithSize;
diff --git a/device/usb/usb_service_impl.h b/device/usb/usb_service_impl.h index f61e591..0868c08 100644 --- a/device/usb/usb_service_impl.h +++ b/device/usb/usb_service_impl.h
@@ -19,7 +19,7 @@ #if defined(OS_WIN) #include "base/scoped_observer.h" -#include "device/core/device_monitor_win.h" +#include "device/base/device_monitor_win.h" #endif // OS_WIN struct libusb_device;
diff --git a/device/usb/usb_service_linux.cc b/device/usb/usb_service_linux.cc index fdd4f89..73c71a7 100644 --- a/device/usb/usb_service_linux.cc +++ b/device/usb/usb_service_linux.cc
@@ -21,7 +21,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "components/device_event_log/device_event_log.h" -#include "device/core/device_monitor_linux.h" +#include "device/base/device_monitor_linux.h" #include "device/usb/usb_device_handle.h" #include "device/usb/usb_device_linux.h" #include "device/usb/webusb_descriptors.h"
diff --git a/docs/linux_faster_builds.md b/docs/linux_faster_builds.md index 9582b38..06c571b5 100644 --- a/docs/linux_faster_builds.md +++ b/docs/linux_faster_builds.md
@@ -41,7 +41,7 @@ The `-B` option is not supported. [relevant commit](https://github.com/icecc/icecream/commit/b2ce5b9cc4bd1900f55c3684214e409fa81e7a92) - linux_use_debug_fission = false + use_debug_fission = false [debug fission](http://gcc.gnu.org/wiki/DebugFission) is not supported. [bug](https://github.com/icecc/icecream/issues/86)
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn index f9a1d1d..e58b1af 100644 --- a/extensions/browser/BUILD.gn +++ b/extensions/browser/BUILD.gn
@@ -265,8 +265,8 @@ "//components/update_client", "//components/variations", "//crypto:platform", + "//device/base", "//device/bluetooth", - "//device/core", "//device/hid", "//device/power_save_blocker", "//device/serial", @@ -318,8 +318,8 @@ "//components/guest_view/browser:test_support", "//components/storage_monitor:test_support", "//content/test:test_support", + "//device/base:mocks", "//device/bluetooth:mocks", - "//device/core:mocks", "//device/hid:mocks", "//device/usb:test_support", "//extensions:test_support",
diff --git a/extensions/browser/api/DEPS b/extensions/browser/api/DEPS index 7dc8543..d1dcf78e 100644 --- a/extensions/browser/api/DEPS +++ b/extensions/browser/api/DEPS
@@ -1,4 +1,4 @@ include_rules = [ - "+device/core", + "+device/base", "+device/hid", ]
diff --git a/extensions/browser/api/device_permissions_manager.cc b/extensions/browser/api/device_permissions_manager.cc index 7a6dac2..f8eebb1 100644 --- a/extensions/browser/api/device_permissions_manager.cc +++ b/extensions/browser/api/device_permissions_manager.cc
@@ -16,7 +16,7 @@ #include "base/values.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "content/public/browser/browser_thread.h" -#include "device/core/device_client.h" +#include "device/base/device_client.h" #include "device/hid/hid_device_info.h" #include "device/hid/hid_service.h" #include "device/usb/usb_device.h"
diff --git a/extensions/browser/api/device_permissions_prompt.cc b/extensions/browser/api/device_permissions_prompt.cc index 96a940f0..a24ade9 100644 --- a/extensions/browser/api/device_permissions_prompt.cc +++ b/extensions/browser/api/device_permissions_prompt.cc
@@ -12,7 +12,7 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" -#include "device/core/device_client.h" +#include "device/base/device_client.h" #include "device/hid/hid_device_filter.h" #include "device/hid/hid_device_info.h" #include "device/hid/hid_service.h"
diff --git a/extensions/browser/api/hid/hid_api.cc b/extensions/browser/api/hid/hid_api.cc index 938b528..48e0ac8 100644 --- a/extensions/browser/api/hid/hid_api.cc +++ b/extensions/browser/api/hid/hid_api.cc
@@ -11,7 +11,7 @@ #include <vector> #include "base/memory/ptr_util.h" -#include "device/core/device_client.h" +#include "device/base/device_client.h" #include "device/hid/hid_connection.h" #include "device/hid/hid_device_filter.h" #include "device/hid/hid_device_info.h"
diff --git a/extensions/browser/api/hid/hid_apitest.cc b/extensions/browser/api/hid/hid_apitest.cc index 9ff411c..e583f5f 100644 --- a/extensions/browser/api/hid/hid_apitest.cc +++ b/extensions/browser/api/hid/hid_apitest.cc
@@ -10,7 +10,7 @@ #include "base/run_loop.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" -#include "device/core/mock_device_client.h" +#include "device/base/mock_device_client.h" #include "device/hid/hid_collection_info.h" #include "device/hid/hid_connection.h" #include "device/hid/hid_device_info.h"
diff --git a/extensions/browser/api/hid/hid_device_manager.cc b/extensions/browser/api/hid/hid_device_manager.cc index 8c9ece1..389ea3f 100644 --- a/extensions/browser/api/hid/hid_device_manager.cc +++ b/extensions/browser/api/hid/hid_device_manager.cc
@@ -15,7 +15,7 @@ #include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" -#include "device/core/device_client.h" +#include "device/base/device_client.h" #include "device/hid/hid_device_filter.h" #include "device/hid/hid_service.h" #include "extensions/browser/api/device_permissions_manager.h"
diff --git a/extensions/browser/api/usb/usb_api.cc b/extensions/browser/api/usb/usb_api.cc index 2ece893..a821db89 100644 --- a/extensions/browser/api/usb/usb_api.cc +++ b/extensions/browser/api/usb/usb_api.cc
@@ -13,7 +13,7 @@ #include "base/barrier_closure.h" #include "base/memory/ptr_util.h" -#include "device/core/device_client.h" +#include "device/base/device_client.h" #include "device/usb/usb_descriptors.h" #include "device/usb/usb_device_handle.h" #include "device/usb/usb_service.h"
diff --git a/extensions/browser/api/usb/usb_apitest.cc b/extensions/browser/api/usb/usb_apitest.cc index 65c1688..cfad67d 100644 --- a/extensions/browser/api/usb/usb_apitest.cc +++ b/extensions/browser/api/usb/usb_apitest.cc
@@ -9,7 +9,7 @@ #include "base/memory/ptr_util.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/test_utils.h" -#include "device/core/mock_device_client.h" +#include "device/base/mock_device_client.h" #include "device/usb/mock_usb_device.h" #include "device/usb/mock_usb_device_handle.h" #include "device/usb/mock_usb_service.h"
diff --git a/extensions/browser/api/usb/usb_event_router.cc b/extensions/browser/api/usb/usb_event_router.cc index 31b550c1..2b811075 100644 --- a/extensions/browser/api/usb/usb_event_router.cc +++ b/extensions/browser/api/usb/usb_event_router.cc
@@ -6,7 +6,7 @@ #include <utility> -#include "device/core/device_client.h" +#include "device/base/device_client.h" #include "device/usb/usb_device.h" #include "extensions/browser/api/device_permissions_manager.h" #include "extensions/browser/api/usb/usb_guid_map.h"
diff --git a/extensions/browser/api/usb/usb_guid_map.cc b/extensions/browser/api/usb/usb_guid_map.cc index 8d65d07a..16f380e 100644 --- a/extensions/browser/api/usb/usb_guid_map.cc +++ b/extensions/browser/api/usb/usb_guid_map.cc
@@ -8,7 +8,7 @@ #include "base/lazy_instance.h" #include "base/strings/utf_string_conversions.h" -#include "device/core/device_client.h" +#include "device/base/device_client.h" #include "device/usb/usb_device.h" #include "device/usb/usb_service.h" #include "extensions/common/api/usb.h"
diff --git a/extensions/renderer/BUILD.gn b/extensions/renderer/BUILD.gn index bfdc697..0d4fd28c 100644 --- a/extensions/renderer/BUILD.gn +++ b/extensions/renderer/BUILD.gn
@@ -16,10 +16,14 @@ "api/display_source/display_source_session.h", "api_activity_logger.cc", "api_activity_logger.h", + "api_binding.cc", + "api_binding.h", "api_definitions_natives.cc", "api_definitions_natives.h", "app_window_custom_bindings.cc", "app_window_custom_bindings.h", + "argument_spec.cc", + "argument_spec.h", "binding_generating_native_handler.cc", "binding_generating_native_handler.h", "blob_native_handler.cc", @@ -251,9 +255,11 @@ sources = [ "activity_log_converter_strategy_unittest.cc", "api/mojo_private/mojo_private_unittest.cc", + "api_binding_unittest.cc", "api_test_base.cc", "api_test_base.h", "api_test_base_unittest.cc", + "argument_spec_unittest.cc", "event_unittest.cc", "gc_callback_unittest.cc", "json_schema_unittest.cc", @@ -274,6 +280,7 @@ ":renderer", "//base", "//extensions:extensions_renderer_resources", + "//gin:gin_test", # TODO(brettw) these tests should not be including headers from browser. "//extensions/browser/mojo",
diff --git a/extensions/renderer/api_binding.cc b/extensions/renderer/api_binding.cc new file mode 100644 index 0000000..d53dbac6 --- /dev/null +++ b/extensions/renderer/api_binding.cc
@@ -0,0 +1,191 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/renderer/api_binding.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "base/strings/stringprintf.h" +#include "base/values.h" +#include "content/public/child/v8_value_converter.h" +#include "extensions/common/extension_api.h" +#include "extensions/renderer/argument_spec.h" +#include "extensions/renderer/v8_helpers.h" +#include "gin/arguments.h" +#include "gin/per_context_data.h" + +namespace extensions { + +namespace { + +const char kExtensionAPIPerContextKey[] = "extension_api_binding"; + +using APISignature = std::vector<std::unique_ptr<ArgumentSpec>>; + +// Returns the expected APISignature for a dictionary describing an API method. +std::unique_ptr<APISignature> GetAPISignature( + const base::DictionaryValue& dict) { + std::unique_ptr<APISignature> signature = base::MakeUnique<APISignature>(); + const base::ListValue* params = nullptr; + CHECK(dict.GetList("parameters", ¶ms)); + signature->reserve(params->GetSize()); + for (const auto& value : *params) { + const base::DictionaryValue* param = nullptr; + CHECK(value->GetAsDictionary(¶m)); + std::string name; + CHECK(param->GetString("name", &name)); + signature->push_back(base::MakeUnique<ArgumentSpec>(*param)); + } + return signature; +} + +// Attempts to match an argument from |arguments| to the given |spec|. +// If the next argmument does not match and |spec| is optional, a null +// base::Value is returned. +// If the argument matches, |arguments| is advanced and the converted value is +// returned. +// If the argument does not match and it is not optional, returns null and +// populates error. +std::unique_ptr<base::Value> ParseArgument(const ArgumentSpec& spec, + v8::Local<v8::Context> context, + gin::Arguments* arguments, + std::string* error) { + v8::Local<v8::Value> value = arguments->PeekNext(); + if (value.IsEmpty() || value->IsNull() || value->IsUndefined()) { + if (!spec.optional()) { + *error = "Missing required argument: " + spec.name(); + return nullptr; + } + // This is safe to call even if |arguments| is at the end (which can happen + // if n optional arguments are omitted at the end of the signature). + arguments->Skip(); + return base::Value::CreateNullValue(); + } + + std::unique_ptr<base::Value> result = + spec.ConvertArgument(context, value, error); + if (!result) { + if (!spec.optional()) { + *error = "Missing required argument: " + spec.name(); + return nullptr; + } + return base::Value::CreateNullValue(); + } + + arguments->Skip(); + return result; +} + +// Parses |args| against |signature| and populates error with any errors. +std::unique_ptr<base::ListValue> ParseArguments(const APISignature* signature, + gin::Arguments* arguments, + std::string* error) { + auto results = base::MakeUnique<base::ListValue>(); + + v8::Local<v8::Context> context = arguments->isolate()->GetCurrentContext(); + + for (const auto& argument_spec : *signature) { + std::unique_ptr<base::Value> parsed = + ParseArgument(*argument_spec, context, arguments, error); + if (!parsed) + return nullptr; + results->Append(std::move(parsed)); + } + + if (!arguments->PeekNext().IsEmpty()) + return nullptr; // Extra arguments aren't allowed. + + return results; +} + +void CallbackHelper(const v8::FunctionCallbackInfo<v8::Value>& info) { + gin::Arguments args(info); + v8::Local<v8::External> external; + CHECK(args.GetData(&external)); + auto callback = static_cast<APIBinding::HandlerCallback*>(external->Value()); + callback->Run(&args); +} + +} // namespace + +APIBinding::APIPerContextData::APIPerContextData() {} +APIBinding::APIPerContextData::~APIPerContextData() {} + +APIBinding::APIBinding(const std::string& name, + const base::ListValue& function_definitions, + const APIMethodCallback& callback) + : method_callback_(callback), weak_factory_(this) { + DCHECK(!method_callback_.is_null()); + for (const auto& func : function_definitions) { + const base::DictionaryValue* func_dict = nullptr; + CHECK(func->GetAsDictionary(&func_dict)); + std::string name; + CHECK(func_dict->GetString("name", &name)); + std::unique_ptr<APISignature> spec = GetAPISignature(*func_dict); + signatures_[name] = std::move(spec); + } +} + +APIBinding::~APIBinding() {} + +v8::Local<v8::Object> APIBinding::CreateInstance(v8::Local<v8::Context> context, + v8::Isolate* isolate) { + // TODO(devlin): APIs may change depending on which features are available, + // but we should be able to cache the unconditional methods on an object + // template, create the object, and then add any conditional methods. + v8::Local<v8::Object> object = v8::Object::New(isolate); + gin::PerContextData* per_context_data = gin::PerContextData::From(context); + DCHECK(per_context_data); + APIPerContextData* data = static_cast<APIPerContextData*>( + per_context_data->GetUserData(kExtensionAPIPerContextKey)); + if (!data) { + auto api_data = base::MakeUnique<APIPerContextData>(); + data = api_data.get(); + per_context_data->SetUserData(kExtensionAPIPerContextKey, + api_data.release()); + } + for (const auto& sig : signatures_) { + auto handler_callback = base::MakeUnique<HandlerCallback>( + base::Bind(&APIBinding::HandleCall, weak_factory_.GetWeakPtr(), + sig.first, sig.second.get())); + // TODO(devlin): We should be able to cache these in a function template. + v8::MaybeLocal<v8::Function> maybe_function = + v8::Function::New(context, &CallbackHelper, + v8::External::New(isolate, handler_callback.get()), + 0, v8::ConstructorBehavior::kThrow); + data->context_callbacks.push_back(std::move(handler_callback)); + v8::Maybe<bool> success = object->CreateDataProperty( + context, gin::StringToSymbol(isolate, sig.first), + maybe_function.ToLocalChecked()); + DCHECK(success.IsJust()); + DCHECK(success.FromJust()); + } + + return object; +} + +void APIBinding::HandleCall(const std::string& name, + const APISignature* signature, + gin::Arguments* arguments) { + std::string error; + v8::HandleScope handle_scope(arguments->isolate()); + std::unique_ptr<base::ListValue> parsed_arguments; + { + v8::TryCatch try_catch(arguments->isolate()); + parsed_arguments = ParseArguments(signature, arguments, &error); + if (try_catch.HasCaught()) { + DCHECK(!parsed_arguments); + try_catch.ReThrow(); + return; + } + } + if (!parsed_arguments) { + arguments->ThrowTypeError("Invalid invocation"); + return; + } + method_callback_.Run(name, std::move(parsed_arguments)); +} + +} // namespace extensions
diff --git a/extensions/renderer/api_binding.h b/extensions/renderer/api_binding.h new file mode 100644 index 0000000..99f4b7e --- /dev/null +++ b/extensions/renderer/api_binding.h
@@ -0,0 +1,88 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXTENSIONS_RENDERER_API_BINDING_H_ +#define EXTENSIONS_RENDERER_API_BINDING_H_ + +#include <map> +#include <memory> +#include <string> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/supports_user_data.h" +#include "v8/include/v8.h" + +namespace base { +class ListValue; +} + +namespace gin { +class Arguments; +} + +namespace extensions { + +class ArgumentSpec; + +// A class that vends v8::Objects for extension APIs. These APIs have function +// interceptors for all exposed methods, which call back into the APIBinding. +// The APIBinding then matches the calling arguments against an expected method +// signature, throwing an error if they don't match. +// There should only need to be a single APIBinding object for each API, and +// each can vend multiple v8::Objects for different contexts. +// TODO(devlin): What's the lifetime of this object? +class APIBinding { + public: + // The callback to called when an API method is invoked with matching + // arguments. This passes the name of the api method and the arguments it + // was passed. + using APIMethodCallback = + base::Callback<void(const std::string&, + std::unique_ptr<base::ListValue>)>; + using HandlerCallback = base::Callback<void(gin::Arguments*)>; + + APIBinding(const std::string& name, + const base::ListValue& function_definitions, + const APIMethodCallback& callback); + ~APIBinding(); + + // Returns a new v8::Object for the API this APIBinding represents. + v8::Local<v8::Object> CreateInstance(v8::Local<v8::Context> context, + v8::Isolate* isolate); + + private: + using APISignature = std::vector<std::unique_ptr<ArgumentSpec>>; + + // Per-context data that stores the callbacks that are used within the + // context. Since these callbacks are used within v8::Externals, v8 itself + // does not clean them up. + struct APIPerContextData : public base::SupportsUserData::Data { + APIPerContextData(); + ~APIPerContextData() override; + + std::vector<std::unique_ptr<HandlerCallback>> context_callbacks; + }; + + // Handles a call an API method with the given |name| and matches the + // arguments against |signature|. + void HandleCall(const std::string& name, + const APISignature* signature, + gin::Arguments* args); + + // A map from method name to expected signature. + std::map<std::string, std::unique_ptr<APISignature>> signatures_; + + // The callback to use when an API is invoked with valid arguments. + APIMethodCallback method_callback_; + + base::WeakPtrFactory<APIBinding> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(APIBinding); +}; + +} // namespace extensions + +#endif // EXTENSIONS_RENDERER_API_BINDING_H_
diff --git a/extensions/renderer/api_binding_unittest.cc b/extensions/renderer/api_binding_unittest.cc new file mode 100644 index 0000000..103b443 --- /dev/null +++ b/extensions/renderer/api_binding_unittest.cc
@@ -0,0 +1,217 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/bind.h" +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/memory/ptr_util.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "base/values.h" +#include "extensions/renderer/api_binding.h" +#include "gin/converter.h" +#include "gin/public/context_holder.h" +#include "gin/public/isolate_holder.h" +#include "gin/test/v8_test.h" +#include "gin/try_catch.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "v8/include/v8.h" + +namespace extensions { + +namespace { + +// Function spec; we use single quotes for readability and then replace them. +const char kFunctions[] = + "[{" + " 'name': 'oneString'," + " 'parameters': [{" + " 'type': 'string'," + " 'name': 'str'" + " }]" + "}, {" + " 'name': 'stringAndInt'," + " 'parameters': [{" + " 'type': 'string'," + " 'name': 'str'" + " }, {" + " 'type': 'integer'," + " 'name': 'int'" + " }]" + "}, {" + " 'name': 'stringOptionalIntAndBool'," + " 'parameters': [{" + " 'type': 'string'," + " 'name': 'str'" + " }, {" + " 'type': 'integer'," + " 'name': 'optionalint'," + " 'optional': true" + " }, {" + " 'type': 'boolean'," + " 'name': 'bool'" + " }]" + "}, {" + " 'name': 'oneObject'," + " 'parameters': [{" + " 'type': 'object'," + " 'name': 'foo'," + " 'properties': {" + " 'prop1': {'type': 'string'}," + " 'prop2': {'type': 'string', 'optional': true}" + " }" + " }]" + "}]"; + +// Helper to convert kFunctions into a ListValue of functions after replacing +// single quotes with double quotes. +std::unique_ptr<base::ListValue> GetFunctions() { + std::string functions_str; + base::ReplaceChars(kFunctions, "'", "\"", &functions_str); + std::unique_ptr<base::Value> value = base::JSONReader::Read(functions_str); + EXPECT_TRUE(value); + return base::ListValue::From(std::move(value)); +} + +} // namespace + +class APIBindingTest : public gin::V8Test { + public: + void OnFunctionCall(const std::string& name, + std::unique_ptr<base::ListValue> arguments) { + arguments_ = std::move(arguments); + } + + protected: + APIBindingTest() {} + void SetUp() override { + gin::V8Test::SetUp(); + v8::HandleScope handle_scope(instance_->isolate()); + holder_ = base::MakeUnique<gin::ContextHolder>(instance_->isolate()); + holder_->SetContext( + v8::Local<v8::Context>::New(instance_->isolate(), context_)); + } + + void TearDown() override { + holder_.reset(); + gin::V8Test::TearDown(); + } + + void ExpectPass(v8::Local<v8::Object> object, + const std::string& script_source, + const std::string& expected_json_arguments_single_quotes) { + std::string expected_json_arguments; + base::ReplaceChars(expected_json_arguments_single_quotes.c_str(), "'", "\"", + &expected_json_arguments); + RunTest(object, script_source, true, expected_json_arguments, + std::string()); + } + + void ExpectFailure(v8::Local<v8::Object> object, + const std::string& script_source, + const std::string& expected_error) { + RunTest(object, script_source, false, std::string(), expected_error); + } + + private: + void RunTest(v8::Local<v8::Object> object, + const std::string& script_source, + bool should_pass, + const std::string& expected_json_arguments, + const std::string& expected_error); + + std::unique_ptr<base::ListValue> arguments_; + std::unique_ptr<gin::ContextHolder> holder_; + + DISALLOW_COPY_AND_ASSIGN(APIBindingTest); +}; + +void APIBindingTest::RunTest(v8::Local<v8::Object> object, + const std::string& script_source, + bool should_pass, + const std::string& expected_json_arguments, + const std::string& expected_error) { + EXPECT_FALSE(arguments_); + std::string wrapped_script_source = + base::StringPrintf("(function(obj) { %s })", script_source.c_str()); + v8::Isolate* isolate = instance_->isolate(); + v8::Local<v8::String> source = + gin::StringToV8(isolate, wrapped_script_source); + ASSERT_FALSE(source.IsEmpty()); + + v8::TryCatch try_catch(isolate); + v8::Local<v8::Script> script = v8::Script::Compile(source); + ASSERT_FALSE(script.IsEmpty()); + v8::Local<v8::Value> val = script->Run(); + ASSERT_FALSE(val.IsEmpty()); + v8::Local<v8::Function> func; + ASSERT_TRUE(gin::ConvertFromV8(isolate, val, &func)); + v8::Local<v8::Value> argv[] = {object}; + func->Call(v8::Undefined(isolate), 1, argv); + + if (should_pass) { + EXPECT_FALSE(try_catch.HasCaught()) + << gin::V8ToString(try_catch.Message()->Get()); + EXPECT_TRUE(arguments_); + std::string actual_json; + EXPECT_TRUE(base::JSONWriter::Write(*arguments_, &actual_json)); + EXPECT_EQ(expected_json_arguments, actual_json); + } else { + ASSERT_TRUE(try_catch.HasCaught()) << script_source; + std::string message = gin::V8ToString(try_catch.Message()->Get()); + EXPECT_EQ(expected_error, message); + } + + arguments_.reset(); +} + +TEST_F(APIBindingTest, Test) { + std::unique_ptr<base::ListValue> functions = GetFunctions(); + ASSERT_TRUE(functions); + APIBinding binding( + "test", *functions, + base::Bind(&APIBindingTest::OnFunctionCall, base::Unretained(this))); + + v8::Isolate* isolate = instance_->isolate(); + + v8::HandleScope handle_scope(isolate); + v8::Local<v8::Context> context = + v8::Local<v8::Context>::New(isolate, context_); + + v8::Local<v8::Object> binding_object = + binding.CreateInstance(context, isolate); + + std::string error = "Uncaught TypeError: Invalid invocation"; + ExpectPass(binding_object, "obj.oneString('foo');", "['foo']"); + ExpectPass(binding_object, "obj.oneString('');", "['']"); + ExpectFailure(binding_object, "obj.oneString(1);", error); + ExpectFailure(binding_object, "obj.oneString();", error); + ExpectFailure(binding_object, "obj.oneString({});", error); + ExpectFailure(binding_object, "obj.oneString('foo', 'bar');", error); + + ExpectPass(binding_object, "obj.stringAndInt('foo', 42);", "['foo',42]"); + ExpectPass(binding_object, "obj.stringAndInt('foo', -1);", "['foo',-1]"); + ExpectFailure(binding_object, "obj.stringAndInt(1);", error); + ExpectFailure(binding_object, "obj.stringAndInt('foo');", error); + ExpectFailure(binding_object, "obj.stringAndInt(1, 'foo');", error); + ExpectFailure(binding_object, "obj.stringAndInt('foo', 'foo');", error); + ExpectFailure(binding_object, "obj.stringAndInt('foo', '1');", error); + ExpectFailure(binding_object, "obj.stringAndInt('foo', 2.3);", error); + + ExpectPass(binding_object, "obj.stringOptionalIntAndBool('foo', 42, true);", + "['foo',42,true]"); + ExpectPass(binding_object, "obj.stringOptionalIntAndBool('foo', true);", + "['foo',null,true]"); + ExpectFailure(binding_object, + "obj.stringOptionalIntAndBool('foo', 'bar', true);", error); + + ExpectPass(binding_object, + "obj.oneObject({prop1: 'foo'});", "[{'prop1':'foo'}]"); + ExpectFailure( + binding_object, + "obj.oneObject({ get prop1() { throw new Error('Badness'); } });", + "Uncaught Error: Badness"); +} + +} // namespace extensions
diff --git a/extensions/renderer/argument_spec.cc b/extensions/renderer/argument_spec.cc new file mode 100644 index 0000000..abd2f96b --- /dev/null +++ b/extensions/renderer/argument_spec.cc
@@ -0,0 +1,229 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/renderer/argument_spec.h" + +#include "base/memory/ptr_util.h" +#include "base/values.h" +#include "content/public/child/v8_value_converter.h" +#include "gin/converter.h" +#include "gin/dictionary.h" + +namespace extensions { + +namespace { + +template <class T> +std::unique_ptr<base::Value> GetFundamentalConvertedValueHelper( + v8::Local<v8::Value> arg, + v8::Local<v8::Context> context, + const base::Optional<int>& minimum) { + T val; + if (!gin::Converter<T>::FromV8(context->GetIsolate(), arg, &val)) + return nullptr; + if (minimum && val < minimum.value()) + return nullptr; + return base::MakeUnique<base::FundamentalValue>(val); +} + +} // namespace + +ArgumentSpec::ArgumentSpec(const base::Value& value) + : type_(ArgumentType::INTEGER), optional_(false) { + const base::DictionaryValue* dict = nullptr; + CHECK(value.GetAsDictionary(&dict)); + std::string type_string; + CHECK(dict->GetString("type", &type_string)); + if (type_string == "integer") + type_ = ArgumentType::INTEGER; + else if (type_string == "number") + type_ = ArgumentType::DOUBLE; + else if (type_string == "object") + type_ = ArgumentType::OBJECT; + else if (type_string == "array") + type_ = ArgumentType::LIST; + else if (type_string == "boolean") + type_ = ArgumentType::BOOLEAN; + else if (type_string == "string") + type_ = ArgumentType::STRING; + else if (type_string == "any") + type_ = ArgumentType::ANY; + else if (type_string == "function") + type_ = ArgumentType::FUNCTION; + else + NOTREACHED(); + + dict->GetBoolean("optional", &optional_); + dict->GetString("name", &name_); + + int min = 0; + if (dict->GetInteger("minimum", &min)) + minimum_ = min; + + const base::DictionaryValue* properties_value = nullptr; + if (type_ == ArgumentType::OBJECT && + dict->GetDictionary("properties", &properties_value)) { + for (base::DictionaryValue::Iterator iter(*properties_value); + !iter.IsAtEnd(); iter.Advance()) { + properties_[iter.key()] = base::MakeUnique<ArgumentSpec>(iter.value()); + } + } else if (type_ == ArgumentType::LIST) { + const base::DictionaryValue* item_value = nullptr; + CHECK(dict->GetDictionary("items", &item_value)); + list_element_type_ = base::MakeUnique<ArgumentSpec>(*item_value); + } +} + +ArgumentSpec::~ArgumentSpec() {} + +std::unique_ptr<base::Value> ArgumentSpec::ConvertArgument( + v8::Local<v8::Context> context, + v8::Local<v8::Value> value, + std::string* error) const { + // TODO(devlin): Support functions? + DCHECK_NE(type_, ArgumentType::FUNCTION); + if (IsFundamentalType()) + return ConvertArgumentToFundamental(context, value, error); + if (type_ == ArgumentType::OBJECT) { + // TODO(devlin): Currently, this would accept an array (if that array had + // all the requisite properties). Is that the right thing to do? + if (!value->IsObject()) { + *error = "Wrong type"; + return nullptr; + } + v8::Local<v8::Object> object = value.As<v8::Object>(); + return ConvertArgumentToObject(context, object, error); + } + if (type_ == ArgumentType::LIST) { + if (!value->IsArray()) { + *error = "Wrong type"; + return nullptr; + } + v8::Local<v8::Array> array = value.As<v8::Array>(); + return ConvertArgumentToArray(context, array, error); + } + if (type_ == ArgumentType::ANY) + return ConvertArgumentToAny(context, value, error); + NOTREACHED(); + return nullptr; +} + +bool ArgumentSpec::IsFundamentalType() const { + return type_ == ArgumentType::INTEGER || type_ == ArgumentType::DOUBLE || + type_ == ArgumentType::BOOLEAN || type_ == ArgumentType::STRING; +} + +std::unique_ptr<base::Value> ArgumentSpec::ConvertArgumentToFundamental( + v8::Local<v8::Context> context, + v8::Local<v8::Value> value, + std::string* error) const { + DCHECK(IsFundamentalType()); + switch (type_) { + case ArgumentType::INTEGER: + return GetFundamentalConvertedValueHelper<int32_t>(value, context, + minimum_); + case ArgumentType::DOUBLE: + return GetFundamentalConvertedValueHelper<double>(value, context, + minimum_); + case ArgumentType::STRING: { + std::string s; + // TODO(devlin): If base::StringValue ever takes a std::string&&, we could + // use std::move to construct. + if (gin::Converter<std::string>::FromV8(context->GetIsolate(), value, &s)) + return base::MakeUnique<base::StringValue>(s); + return nullptr; + } + case ArgumentType::BOOLEAN: { + bool b = false; + if (value->IsBoolean() && + gin::Converter<bool>::FromV8(context->GetIsolate(), value, &b)) { + return base::MakeUnique<base::FundamentalValue>(b); + } + return nullptr; + } + default: + NOTREACHED(); + } + return nullptr; +} + +std::unique_ptr<base::Value> ArgumentSpec::ConvertArgumentToObject( + v8::Local<v8::Context> context, + v8::Local<v8::Object> object, + std::string* error) const { + DCHECK_EQ(ArgumentType::OBJECT, type_); + auto result = base::MakeUnique<base::DictionaryValue>(); + gin::Dictionary dictionary(context->GetIsolate(), object); + for (const auto& kv : properties_) { + v8::Local<v8::Value> subvalue; + // See comment in ConvertArgumentToArray() about passing in custom crazy + // values here. + // TODO(devlin): gin::Dictionary::Get() uses Isolate::GetCurrentContext() - + // is that always right here, or should we use the v8::Object APIs and + // pass in |context|? + // TODO(devlin): Hyper-optimization - Dictionary::Get() also creates a new + // v8::String for each call. Hypothetically, we could cache these, or at + // least use an internalized string. + if (!dictionary.Get(kv.first, &subvalue)) + return nullptr; + + if (subvalue.IsEmpty() || subvalue->IsNull() || subvalue->IsUndefined()) { + if (!kv.second->optional_) { + *error = "Missing key: " + kv.first; + return nullptr; + } + continue; + } + std::unique_ptr<base::Value> property = + kv.second->ConvertArgument(context, subvalue, error); + if (!property) + return nullptr; + result->Set(kv.first, std::move(property)); + } + return std::move(result); +} + +std::unique_ptr<base::Value> ArgumentSpec::ConvertArgumentToArray( + v8::Local<v8::Context> context, + v8::Local<v8::Array> value, + std::string* error) const { + DCHECK_EQ(ArgumentType::LIST, type_); + auto result = base::MakeUnique<base::ListValue>(); + uint32_t length = value->Length(); + for (uint32_t i = 0; i < length; ++i) { + v8::MaybeLocal<v8::Value> maybe_subvalue = value->Get(context, i); + v8::Local<v8::Value> subvalue; + // Note: This can fail in the case of a developer passing in the following: + // var a = []; + // Object.defineProperty(a, 0, { get: () => { throw new Error('foo'); } }); + // Currently, this will cause the developer-specified error ('foo') to be + // thrown. + // TODO(devlin): This is probably fine, but it's worth contemplating + // catching the error and throwing our own. + if (!maybe_subvalue.ToLocal(&subvalue)) + return nullptr; + std::unique_ptr<base::Value> item = + list_element_type_->ConvertArgument(context, subvalue, error); + if (!item) + return nullptr; + result->Append(std::move(item)); + } + return std::move(result); +} + +std::unique_ptr<base::Value> ArgumentSpec::ConvertArgumentToAny( + v8::Local<v8::Context> context, + v8::Local<v8::Value> value, + std::string* error) const { + DCHECK_EQ(ArgumentType::ANY, type_); + std::unique_ptr<content::V8ValueConverter> converter( + content::V8ValueConverter::create()); + std::unique_ptr<base::Value> converted( + converter->FromV8Value(value, context)); + if (!converted) + *error = "Could not convert to 'any'."; + return converted; +} + +} // namespace extensions
diff --git a/extensions/renderer/argument_spec.h b/extensions/renderer/argument_spec.h new file mode 100644 index 0000000..1ca0ff8 --- /dev/null +++ b/extensions/renderer/argument_spec.h
@@ -0,0 +1,99 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXTENSIONS_RENDERER_ARGUMENT_SPEC_H_ +#define EXTENSIONS_RENDERER_ARGUMENT_SPEC_H_ + +#include <map> +#include <memory> +#include <string> +#include <vector> + +#include "base/macros.h" +#include "base/optional.h" +#include "v8/include/v8.h" + +namespace base { +class Value; +} + +namespace extensions { + +enum class ArgumentType { + INTEGER, + DOUBLE, + BOOLEAN, + STRING, + OBJECT, + LIST, + FUNCTION, + ANY, +}; + +// A description of a given Argument to an Extension. +class ArgumentSpec { + public: + // Reads the description from |value| and sets associated fields. + // TODO(devlin): We should strongly think about generating these instead of + // populating them at runtime. + explicit ArgumentSpec(const base::Value& value); + ~ArgumentSpec(); + + // Returns the converted base::Value or null if the |value| didn't match. + std::unique_ptr<base::Value> ConvertArgument(v8::Local<v8::Context> context, + v8::Local<v8::Value> value, + std::string* error) const; + + const std::string& name() const { return name_; } + bool optional() const { return optional_; } + ArgumentType type() const { return type_; } + + private: + // Returns true if this argument refers to a fundamental type. + bool IsFundamentalType() const; + + // Conversion functions. These should only be used if the spec is of the given + // type (otherwise, they will DCHECK). + std::unique_ptr<base::Value> ConvertArgumentToFundamental( + v8::Local<v8::Context> context, + v8::Local<v8::Value> value, + std::string* error) const; + std::unique_ptr<base::Value> ConvertArgumentToObject( + v8::Local<v8::Context> context, + v8::Local<v8::Object> object, + std::string* error) const; + std::unique_ptr<base::Value> ConvertArgumentToArray( + v8::Local<v8::Context> context, + v8::Local<v8::Array> value, + std::string* error) const; + std::unique_ptr<base::Value> ConvertArgumentToAny( + v8::Local<v8::Context> context, + v8::Local<v8::Value> value, + std::string* error) const; + + // The name of the argument. + std::string name_; + + // The type of the argument. + ArgumentType type_; + + // Whether or not the argument is required. + bool optional_; + + // A minimum, if any. + base::Optional<int> minimum_; + + // A map of required properties; present only for objects. Note that any + // properties *not* defined in this map will be dropped during conversion. + std::map<std::string, std::unique_ptr<ArgumentSpec>> properties_; + + // The type of item that should be in the list; present only for lists. + std::unique_ptr<ArgumentSpec> list_element_type_; + + DISALLOW_COPY_AND_ASSIGN(ArgumentSpec); +}; + +} // namespace extensions + +#endif // EXTENSIONS_RENDERER_ARGUMENT_SPEC_H_
diff --git a/extensions/renderer/argument_spec_unittest.cc b/extensions/renderer/argument_spec_unittest.cc new file mode 100644 index 0000000..832e1b8 --- /dev/null +++ b/extensions/renderer/argument_spec_unittest.cc
@@ -0,0 +1,213 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/strings/string_util.h" +#include "base/values.h" +#include "extensions/renderer/argument_spec.h" +#include "gin/converter.h" +#include "gin/public/isolate_holder.h" +#include "gin/test/v8_test.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "v8/include/v8.h" + +namespace extensions { + +namespace { + +// Returns a parsed version of |str|, substituting double quotes for single +// quotes. +std::unique_ptr<base::Value> GetValue(const std::string& str) { + std::string updated; + base::ReplaceChars(str.c_str(), "'", "\"", &updated); + std::unique_ptr<base::Value> value = base::JSONReader::Read(updated); + CHECK(value); + return value; +} + +} // namespace + +class ArgumentSpecUnitTest : public gin::V8Test { + protected: + ArgumentSpecUnitTest() {} + ~ArgumentSpecUnitTest() override {} + void ExpectSuccess(const ArgumentSpec& spec, + const std::string& script_source, + const std::string& expected_json_single_quotes) { + std::string expected_json; + base::ReplaceChars(expected_json_single_quotes.c_str(), "'", "\"", + &expected_json); + RunTest(spec, script_source, TestResult::PASS, expected_json, + std::string()); + } + + void ExpectFailure(const ArgumentSpec& spec, + const std::string& script_source) { + RunTest(spec, script_source, TestResult::FAIL, std::string(), + std::string()); + } + + void ExpectThrow(const ArgumentSpec& spec, + const std::string& script_source, + const std::string& expected_thrown_message) { + RunTest(spec, script_source, TestResult::THROW, std::string(), + expected_thrown_message); + } + + private: + enum class TestResult { PASS, FAIL, THROW, }; + + void RunTest(const ArgumentSpec& spec, + const std::string& script_source, + TestResult expected_result, + const std::string& expected_json, + const std::string& expected_thrown_message); + + DISALLOW_COPY_AND_ASSIGN(ArgumentSpecUnitTest); +}; + +void ArgumentSpecUnitTest::RunTest(const ArgumentSpec& spec, + const std::string& script_source, + TestResult expected_result, + const std::string& expected_json, + const std::string& expected_thrown_message) { + v8::Isolate* isolate = instance_->isolate(); + v8::HandleScope handle_scope(instance_->isolate()); + v8::Local<v8::String> source = gin::StringToV8(isolate, script_source); + ASSERT_FALSE(source.IsEmpty()); + + v8::Local<v8::Context> context = + v8::Local<v8::Context>::New(instance_->isolate(), context_); + v8::Local<v8::Script> script = v8::Script::Compile(source); + ASSERT_FALSE(script.IsEmpty()) << script_source; + v8::TryCatch try_catch(isolate); + v8::Local<v8::Value> val = script->Run(); + ASSERT_FALSE(val.IsEmpty()) << script_source; + + std::string error; + std::unique_ptr<base::Value> out_value = + spec.ConvertArgument(context, val, &error); + bool should_succeed = expected_result == TestResult::PASS; + ASSERT_EQ(should_succeed, !!out_value) << script_source << ", " << error; + bool should_throw = expected_result == TestResult::THROW; + ASSERT_EQ(should_throw, try_catch.HasCaught()) << script_source; + if (should_succeed) { + ASSERT_TRUE(out_value); + std::string actual_json; + EXPECT_TRUE(base::JSONWriter::Write(*out_value, &actual_json)); + EXPECT_EQ(expected_json, actual_json); + } else if (should_throw) { + EXPECT_EQ(expected_thrown_message, + gin::V8ToString(try_catch.Message()->Get())); + } +} + +TEST_F(ArgumentSpecUnitTest, Test) { + { + ArgumentSpec spec(*GetValue("{'type': 'integer'}")); + ExpectSuccess(spec, "1", "1"); + ExpectSuccess(spec, "-1", "-1"); + ExpectSuccess(spec, "0", "0"); + ExpectFailure(spec, "undefined"); + ExpectFailure(spec, "null"); + ExpectFailure(spec, "'foo'"); + ExpectFailure(spec, "'1'"); + ExpectFailure(spec, "{}"); + ExpectFailure(spec, "[1]"); + } + + { + ArgumentSpec spec(*GetValue("{'type': 'integer', 'minimum': 1}")); + ExpectSuccess(spec, "2", "2"); + ExpectSuccess(spec, "1", "1"); + ExpectFailure(spec, "0"); + ExpectFailure(spec, "-1"); + } + + { + ArgumentSpec spec(*GetValue("{'type': 'string'}")); + ExpectSuccess(spec, "'foo'", "'foo'"); + ExpectSuccess(spec, "''", "''"); + ExpectFailure(spec, "1"); + ExpectFailure(spec, "{}"); + ExpectFailure(spec, "['foo']"); + } + + { + ArgumentSpec spec(*GetValue("{'type': 'boolean'}")); + ExpectSuccess(spec, "true", "true"); + ExpectSuccess(spec, "false", "false"); + ExpectFailure(spec, "1"); + ExpectFailure(spec, "'true'"); + ExpectFailure(spec, "null"); + } + + { + ArgumentSpec spec( + *GetValue("{'type': 'array', 'items': {'type': 'string'}}")); + ExpectSuccess(spec, "[]", "[]"); + ExpectSuccess(spec, "['foo']", "['foo']"); + ExpectSuccess(spec, "['foo', 'bar']", "['foo','bar']"); + ExpectSuccess(spec, "var x = new Array(); x[0] = 'foo'; x;", "['foo']"); + ExpectFailure(spec, "'foo'"); + ExpectFailure(spec, "[1, 2]"); + ExpectFailure(spec, "['foo', 1]"); + ExpectThrow( + spec, + "var x = [];" + "Object.defineProperty(" + " x, 0," + " { get: () => { throw new Error('Badness'); } });" + "x;", + "Uncaught Error: Badness"); + } + + { + const char kObjectSpec[] = + "{" + " 'type': 'object'," + " 'properties': {" + " 'prop1': {'type': 'string'}," + " 'prop2': {'type': 'integer', 'optional': true}" + " }" + "}"; + ArgumentSpec spec(*GetValue(kObjectSpec)); + ExpectSuccess(spec, "({prop1: 'foo', prop2: 2})", + "{'prop1':'foo','prop2':2}"); + ExpectSuccess(spec, "({prop1: 'foo', prop2: 2, prop3: 'blah'})", + "{'prop1':'foo','prop2':2}"); + ExpectSuccess(spec, "({prop1: 'foo'})", "{'prop1':'foo'}"); + ExpectSuccess(spec, "({prop1: 'foo', prop2: null})", "{'prop1':'foo'}"); + ExpectSuccess(spec, "x = {}; x.prop1 = 'foo'; x;", "{'prop1':'foo'}"); + ExpectSuccess( + spec, + "function X() {}\n" + "X.prototype = { prop1: 'foo' };\n" + "function Y() { this.__proto__ = X.prototype; }\n" + "var z = new Y();\n" + "z;", + "{'prop1':'foo'}"); + ExpectFailure(spec, "({prop1: 'foo', prop2: 'bar'})"); + ExpectFailure(spec, "({prop2: 2})"); + // Self-referential fun. Currently we don't have to worry about these much + // because the spec won't match at some point (and V8ValueConverter has + // cycle detection and will fail). + ExpectFailure(spec, "x = {}; x.prop1 = x; x;"); + ExpectThrow( + spec, + "({ get prop1() { throw new Error('Badness'); }});", + "Uncaught Error: Badness"); + ExpectThrow( + spec, + "x = {prop1: 'foo'};\n" + "Object.defineProperty(\n" + " x, 'prop2',\n" + " { get: () => { throw new Error('Badness'); } });\n" + "x;", + "Uncaught Error: Badness"); + } +} + +} // namespace extensions
diff --git a/extensions/renderer/module_system.cc b/extensions/renderer/module_system.cc index f3fdf5d..55c7bab 100644 --- a/extensions/renderer/module_system.cc +++ b/extensions/renderer/module_system.cc
@@ -111,6 +111,22 @@ LOG(ERROR) << "Failed to set private property on the export."; } +bool ContextNeedsMojoBindings(ScriptContext* context) { + // Mojo is only used from JS by some APIs so a context only needs the mojo + // bindings if at least one is available. + // + // Prefer to use Mojo from C++ if possible rather than adding to this list. + static const char* const kApisRequiringMojo[] = { + "mimeHandlerPrivate", "mojoPrivate", + }; + + for (const auto* api : kApisRequiringMojo) { + if (context->GetAvailability(api).is_available()) + return true; + } + return false; +} + } // namespace std::string ModuleSystem::ExceptionHandler::CreateExceptionString( @@ -169,12 +185,9 @@ SetPrivate(global, kModuleSystem, v8::External::New(isolate, this)); gin::ModuleRegistry::From(context->v8_context())->AddObserver(this); - // TODO(devlin): We really shouldn't be injecting mojo into every blessed - // extension context - it's wasteful. But it's better than injecting into - // every frame (previous behavior) so start with this while we investigate - // further. See crbug.com/636655. if (context_->GetRenderFrame() && - context_->context_type() == Feature::BLESSED_EXTENSION_CONTEXT) { + context_->context_type() == Feature::BLESSED_EXTENSION_CONTEXT && + ContextNeedsMojoBindings(context_)) { context_->GetRenderFrame()->EnsureMojoBuiltinsAreAvailable( context->isolate(), context->v8_context()); }
diff --git a/extensions/shell/BUILD.gn b/extensions/shell/BUILD.gn index eddb55e1..a690629 100644 --- a/extensions/shell/BUILD.gn +++ b/extensions/shell/BUILD.gn
@@ -37,7 +37,7 @@ "//components/web_cache/renderer", "//content", "//content/shell:content_shell_lib", - "//device/core", + "//device/base", "//device/hid", "//extensions:extensions_resources", "//extensions:shell_and_test_pak",
diff --git a/extensions/shell/browser/DEPS b/extensions/shell/browser/DEPS index bd690ad..e834fe1 100644 --- a/extensions/shell/browser/DEPS +++ b/extensions/shell/browser/DEPS
@@ -17,8 +17,8 @@ "+content/shell/browser/shell_url_request_context_getter.h", # For device backend support. + "+device/base", "+device/bluetooth", - "+device/core", "+device/hid", "+device/usb",
diff --git a/extensions/shell/browser/shell_device_client.h b/extensions/shell/browser/shell_device_client.h index 7da2dba..ae4bac1 100644 --- a/extensions/shell/browser/shell_device_client.h +++ b/extensions/shell/browser/shell_device_client.h
@@ -9,7 +9,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" -#include "device/core/device_client.h" +#include "device/base/device_client.h" namespace extensions {
diff --git a/ios/build/bots/chromium.fyi/GomaCanaryiOS.json b/ios/build/bots/chromium.fyi/GomaCanaryiOS.json new file mode 100644 index 0000000..2c55c02 --- /dev/null +++ b/ios/build/bots/chromium.fyi/GomaCanaryiOS.json
@@ -0,0 +1,32 @@ +{ + "owners": [ + "yyanagisawa" + ], + "comments": [ + "Goma canary builder for iOS." + ], + "xcode version": "8.0", + "GYP_DEFINES": [ + "OS=ios", + "chromium_ios_signing=0", + "component=static_library", + "use_goma=1", + "gomadir=$(goma_dir)", + "target_subarch=arm32" + ], + "gn_args": [ + "ios_enable_code_signing=false", + "is_component_build=false", + "use_goma=true", + "goma_dir=\"$(goma_dir)\"", + "target_cpu=\"arm\"", + "target_os=\"ios\"" + ], + "mb_type": "gn", + "compiler": "ninja", + "additional_compile_targets": ["gn_all"], + "configuration": "Release", + "sdk": "iphoneos10.0", + "tests": [ + ] +}
diff --git a/ios/chrome/app/theme/default_100_percent/controlled_setting_mandatory.png b/ios/chrome/app/theme/default_100_percent/controlled_setting_mandatory.png new file mode 100644 index 0000000..5735ead5 --- /dev/null +++ b/ios/chrome/app/theme/default_100_percent/controlled_setting_mandatory.png Binary files differ
diff --git a/ios/chrome/app/theme/default_100_percent/omnibox_history.png b/ios/chrome/app/theme/default_100_percent/omnibox_history.png new file mode 100644 index 0000000..9b63e262 --- /dev/null +++ b/ios/chrome/app/theme/default_100_percent/omnibox_history.png Binary files differ
diff --git a/ios/chrome/app/theme/default_100_percent/omnibox_history_incognito.png b/ios/chrome/app/theme/default_100_percent/omnibox_history_incognito.png new file mode 100644 index 0000000..418d0b4 --- /dev/null +++ b/ios/chrome/app/theme/default_100_percent/omnibox_history_incognito.png Binary files differ
diff --git a/ios/chrome/app/theme/default_100_percent/omnibox_http.png b/ios/chrome/app/theme/default_100_percent/omnibox_http.png new file mode 100644 index 0000000..8de583e --- /dev/null +++ b/ios/chrome/app/theme/default_100_percent/omnibox_http.png Binary files differ
diff --git a/ios/chrome/app/theme/default_100_percent/omnibox_http_incognito.png b/ios/chrome/app/theme/default_100_percent/omnibox_http_incognito.png new file mode 100644 index 0000000..2f5e5e8d --- /dev/null +++ b/ios/chrome/app/theme/default_100_percent/omnibox_http_incognito.png Binary files differ
diff --git a/ios/chrome/app/theme/default_100_percent/omnibox_https_invalid.png b/ios/chrome/app/theme/default_100_percent/omnibox_https_invalid.png new file mode 100644 index 0000000..ba50e5e --- /dev/null +++ b/ios/chrome/app/theme/default_100_percent/omnibox_https_invalid.png Binary files differ
diff --git a/ios/chrome/app/theme/default_100_percent/omnibox_https_valid.png b/ios/chrome/app/theme/default_100_percent/omnibox_https_valid.png new file mode 100644 index 0000000..9337d655 --- /dev/null +++ b/ios/chrome/app/theme/default_100_percent/omnibox_https_valid.png Binary files differ
diff --git a/ios/chrome/app/theme/default_100_percent/omnibox_search.png b/ios/chrome/app/theme/default_100_percent/omnibox_search.png new file mode 100644 index 0000000..2a8eb96 --- /dev/null +++ b/ios/chrome/app/theme/default_100_percent/omnibox_search.png Binary files differ
diff --git a/ios/chrome/app/theme/default_100_percent/omnibox_search_incognito.png b/ios/chrome/app/theme/default_100_percent/omnibox_search_incognito.png new file mode 100644 index 0000000..4c84df0 --- /dev/null +++ b/ios/chrome/app/theme/default_100_percent/omnibox_search_incognito.png Binary files differ
diff --git a/ios/chrome/app/theme/default_100_percent/omnibox_star.png b/ios/chrome/app/theme/default_100_percent/omnibox_star.png new file mode 100644 index 0000000..4a31fecb --- /dev/null +++ b/ios/chrome/app/theme/default_100_percent/omnibox_star.png Binary files differ
diff --git a/ios/chrome/app/theme/default_100_percent/omnibox_star_incognito.png b/ios/chrome/app/theme/default_100_percent/omnibox_star_incognito.png new file mode 100644 index 0000000..b903f5c --- /dev/null +++ b/ios/chrome/app/theme/default_100_percent/omnibox_star_incognito.png Binary files differ
diff --git a/ios/chrome/app/theme/default_200_percent/controlled_setting_mandatory.png b/ios/chrome/app/theme/default_200_percent/controlled_setting_mandatory.png new file mode 100644 index 0000000..ae0fee0f --- /dev/null +++ b/ios/chrome/app/theme/default_200_percent/controlled_setting_mandatory.png Binary files differ
diff --git a/ios/chrome/app/theme/default_200_percent/omnibox_history.png b/ios/chrome/app/theme/default_200_percent/omnibox_history.png new file mode 100644 index 0000000..a1ee7772 --- /dev/null +++ b/ios/chrome/app/theme/default_200_percent/omnibox_history.png Binary files differ
diff --git a/ios/chrome/app/theme/default_200_percent/omnibox_history_incognito.png b/ios/chrome/app/theme/default_200_percent/omnibox_history_incognito.png new file mode 100644 index 0000000..6738098 --- /dev/null +++ b/ios/chrome/app/theme/default_200_percent/omnibox_history_incognito.png Binary files differ
diff --git a/ios/chrome/app/theme/default_200_percent/omnibox_http.png b/ios/chrome/app/theme/default_200_percent/omnibox_http.png new file mode 100644 index 0000000..cf21532 --- /dev/null +++ b/ios/chrome/app/theme/default_200_percent/omnibox_http.png Binary files differ
diff --git a/ios/chrome/app/theme/default_200_percent/omnibox_http_incognito.png b/ios/chrome/app/theme/default_200_percent/omnibox_http_incognito.png new file mode 100644 index 0000000..adb55f15 --- /dev/null +++ b/ios/chrome/app/theme/default_200_percent/omnibox_http_incognito.png Binary files differ
diff --git a/ios/chrome/app/theme/default_200_percent/omnibox_https_invalid.png b/ios/chrome/app/theme/default_200_percent/omnibox_https_invalid.png new file mode 100644 index 0000000..f797139 --- /dev/null +++ b/ios/chrome/app/theme/default_200_percent/omnibox_https_invalid.png Binary files differ
diff --git a/ios/chrome/app/theme/default_200_percent/omnibox_https_valid.png b/ios/chrome/app/theme/default_200_percent/omnibox_https_valid.png new file mode 100644 index 0000000..092bf9b --- /dev/null +++ b/ios/chrome/app/theme/default_200_percent/omnibox_https_valid.png Binary files differ
diff --git a/ios/chrome/app/theme/default_200_percent/omnibox_search.png b/ios/chrome/app/theme/default_200_percent/omnibox_search.png new file mode 100644 index 0000000..72c30de --- /dev/null +++ b/ios/chrome/app/theme/default_200_percent/omnibox_search.png Binary files differ
diff --git a/ios/chrome/app/theme/default_200_percent/omnibox_search_incognito.png b/ios/chrome/app/theme/default_200_percent/omnibox_search_incognito.png new file mode 100644 index 0000000..a1aaa55 --- /dev/null +++ b/ios/chrome/app/theme/default_200_percent/omnibox_search_incognito.png Binary files differ
diff --git a/ios/chrome/app/theme/default_200_percent/omnibox_star.png b/ios/chrome/app/theme/default_200_percent/omnibox_star.png new file mode 100644 index 0000000..e3aa7df6 --- /dev/null +++ b/ios/chrome/app/theme/default_200_percent/omnibox_star.png Binary files differ
diff --git a/ios/chrome/app/theme/default_200_percent/omnibox_star_incognito.png b/ios/chrome/app/theme/default_200_percent/omnibox_star_incognito.png new file mode 100644 index 0000000..62af06b1 --- /dev/null +++ b/ios/chrome/app/theme/default_200_percent/omnibox_star_incognito.png Binary files differ
diff --git a/ios/chrome/app/theme/default_300_percent/controlled_setting_mandatory.png b/ios/chrome/app/theme/default_300_percent/controlled_setting_mandatory.png new file mode 100644 index 0000000..b83207e --- /dev/null +++ b/ios/chrome/app/theme/default_300_percent/controlled_setting_mandatory.png Binary files differ
diff --git a/ios/chrome/app/theme/default_300_percent/omnibox_history.png b/ios/chrome/app/theme/default_300_percent/omnibox_history.png new file mode 100644 index 0000000..cf654021 --- /dev/null +++ b/ios/chrome/app/theme/default_300_percent/omnibox_history.png Binary files differ
diff --git a/ios/chrome/app/theme/default_300_percent/omnibox_history_incognito.png b/ios/chrome/app/theme/default_300_percent/omnibox_history_incognito.png new file mode 100644 index 0000000..44537f1 --- /dev/null +++ b/ios/chrome/app/theme/default_300_percent/omnibox_history_incognito.png Binary files differ
diff --git a/ios/chrome/app/theme/default_300_percent/omnibox_http.png b/ios/chrome/app/theme/default_300_percent/omnibox_http.png new file mode 100644 index 0000000..2830184 --- /dev/null +++ b/ios/chrome/app/theme/default_300_percent/omnibox_http.png Binary files differ
diff --git a/ios/chrome/app/theme/default_300_percent/omnibox_http_incognito.png b/ios/chrome/app/theme/default_300_percent/omnibox_http_incognito.png new file mode 100644 index 0000000..3cb92d6 --- /dev/null +++ b/ios/chrome/app/theme/default_300_percent/omnibox_http_incognito.png Binary files differ
diff --git a/ios/chrome/app/theme/default_300_percent/omnibox_https_invalid.png b/ios/chrome/app/theme/default_300_percent/omnibox_https_invalid.png new file mode 100644 index 0000000..2b63261 --- /dev/null +++ b/ios/chrome/app/theme/default_300_percent/omnibox_https_invalid.png Binary files differ
diff --git a/ios/chrome/app/theme/default_300_percent/omnibox_https_valid.png b/ios/chrome/app/theme/default_300_percent/omnibox_https_valid.png new file mode 100644 index 0000000..c4511c6 --- /dev/null +++ b/ios/chrome/app/theme/default_300_percent/omnibox_https_valid.png Binary files differ
diff --git a/ios/chrome/app/theme/default_300_percent/omnibox_search.png b/ios/chrome/app/theme/default_300_percent/omnibox_search.png new file mode 100644 index 0000000..79ed6e0c --- /dev/null +++ b/ios/chrome/app/theme/default_300_percent/omnibox_search.png Binary files differ
diff --git a/ios/chrome/app/theme/default_300_percent/omnibox_search_incognito.png b/ios/chrome/app/theme/default_300_percent/omnibox_search_incognito.png new file mode 100644 index 0000000..1892d6f --- /dev/null +++ b/ios/chrome/app/theme/default_300_percent/omnibox_search_incognito.png Binary files differ
diff --git a/ios/chrome/app/theme/default_300_percent/omnibox_star.png b/ios/chrome/app/theme/default_300_percent/omnibox_star.png new file mode 100644 index 0000000..3e156e3 --- /dev/null +++ b/ios/chrome/app/theme/default_300_percent/omnibox_star.png Binary files differ
diff --git a/ios/chrome/app/theme/default_300_percent/omnibox_star_incognito.png b/ios/chrome/app/theme/default_300_percent/omnibox_star_incognito.png new file mode 100644 index 0000000..79d035e --- /dev/null +++ b/ios/chrome/app/theme/default_300_percent/omnibox_star_incognito.png Binary files differ
diff --git a/ios/chrome/app/theme/ios_theme_resources.grd b/ios/chrome/app/theme/ios_theme_resources.grd index 81c5a7c6..4e60a6c2 100644 --- a/ios/chrome/app/theme/ios_theme_resources.grd +++ b/ios/chrome/app/theme/ios_theme_resources.grd
@@ -28,6 +28,18 @@ <structure type="chrome_scaled_image" name="IDR_IOS_INFOBAR_AUTOLOGIN" file="infobar_autologin.png" /> <structure type="chrome_scaled_image" name="IDR_IOS_INFOBAR_SAVE_PASSWORD" file="infobar_save_password.png" /> <structure type="chrome_scaled_image" name="IDR_IOS_INFOBAR_TRANSLATE" file="infobar_translate.png" /> + <structure type="chrome_scaled_image" name="IDR_IOS_LOCATION_BAR_HTTP" file="omnibox_http.png" /> + <structure type="chrome_scaled_image" name="IDR_IOS_OMNIBOX_HISTORY" file="omnibox_history.png" /> + <structure type="chrome_scaled_image" name="IDR_IOS_OMNIBOX_HISTORY_INCOGNITO" file="omnibox_history_incognito.png" /> + <structure type="chrome_scaled_image" name="IDR_IOS_OMNIBOX_HTTP" file="omnibox_http.png" /> + <structure type="chrome_scaled_image" name="IDR_IOS_OMNIBOX_HTTPS_INVALID" file="omnibox_https_invalid.png" /> + <structure type="chrome_scaled_image" name="IDR_IOS_OMNIBOX_HTTPS_POLICY_WARNING" file="controlled_setting_mandatory.png" /> + <structure type="chrome_scaled_image" name="IDR_IOS_OMNIBOX_HTTPS_VALID" file="omnibox_https_valid.png" /> + <structure type="chrome_scaled_image" name="IDR_IOS_OMNIBOX_HTTP_INCOGNITO" file="omnibox_http_incognito.png" /> + <structure type="chrome_scaled_image" name="IDR_IOS_OMNIBOX_SEARCH" file="omnibox_search.png" /> + <structure type="chrome_scaled_image" name="IDR_IOS_OMNIBOX_SEARCH_INCOGNITO" file="omnibox_search_incognito.png" /> + <structure type="chrome_scaled_image" name="IDR_IOS_OMNIBOX_STAR" file="omnibox_star.png" /> + <structure type="chrome_scaled_image" name="IDR_IOS_OMNIBOX_STAR_INCOGNITO" file="omnibox_star_incognito.png" /> </structures> </release> </grit>
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn index 564f9a3f..c9def995 100644 --- a/ios/chrome/browser/BUILD.gn +++ b/ios/chrome/browser/BUILD.gn
@@ -507,8 +507,6 @@ "ui/keyboard/hardware_keyboard_watcher.mm", "ui/native_content_controller.h", "ui/native_content_controller.mm", - "ui/omnibox/web_omnibox_edit_controller.cc", - "ui/omnibox/web_omnibox_edit_controller.h", "ui/orientation_limiting_navigation_controller.h", "ui/orientation_limiting_navigation_controller.mm", "ui/prerender_final_status.h",
diff --git a/ios/chrome/browser/ui/omnibox/BUILD.gn b/ios/chrome/browser/ui/omnibox/BUILD.gn new file mode 100644 index 0000000..bf42541 --- /dev/null +++ b/ios/chrome/browser/ui/omnibox/BUILD.gn
@@ -0,0 +1,18 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("omnibox") { + sources = [ + "omnibox_util.cc", + "omnibox_util.h", + "web_omnibox_edit_controller.cc", + "web_omnibox_edit_controller.h", + ] + deps = [ + "//base", + "//components/omnibox/browser", + "//components/security_state", + "//ios/chrome/app/theme", + ] +}
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_util.cc b/ios/chrome/browser/ui/omnibox/omnibox_util.cc new file mode 100644 index 0000000..1fa7c4a --- /dev/null +++ b/ios/chrome/browser/ui/omnibox/omnibox_util.cc
@@ -0,0 +1,69 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/ui/omnibox/omnibox_util.h" + +#include "base/logging.h" +#include "ios/chrome/grit/ios_theme_resources.h" + +int GetIconForAutocompleteMatchType(AutocompleteMatchType::Type type, + bool is_starred, + bool is_incognito) { + if (is_starred) + return is_incognito ? IDR_IOS_OMNIBOX_STAR_INCOGNITO : IDR_IOS_OMNIBOX_STAR; + + switch (type) { + case AutocompleteMatchType::BOOKMARK_TITLE: + case AutocompleteMatchType::CLIPBOARD: + case AutocompleteMatchType::NAVSUGGEST: + case AutocompleteMatchType::NAVSUGGEST_PERSONALIZED: + case AutocompleteMatchType::PHYSICAL_WEB: + case AutocompleteMatchType::PHYSICAL_WEB_OVERFLOW: + case AutocompleteMatchType::URL_WHAT_YOU_TYPED: + return is_incognito ? IDR_IOS_OMNIBOX_HTTP_INCOGNITO + : IDR_IOS_OMNIBOX_HTTP; + case AutocompleteMatchType::HISTORY_BODY: + case AutocompleteMatchType::HISTORY_KEYWORD: + case AutocompleteMatchType::HISTORY_TITLE: + case AutocompleteMatchType::HISTORY_URL: + case AutocompleteMatchType::SEARCH_HISTORY: + return is_incognito ? IDR_IOS_OMNIBOX_HISTORY_INCOGNITO + : IDR_IOS_OMNIBOX_HISTORY; + case AutocompleteMatchType::CONTACT_DEPRECATED: + case AutocompleteMatchType::SEARCH_OTHER_ENGINE: + case AutocompleteMatchType::SEARCH_SUGGEST: + case AutocompleteMatchType::SEARCH_SUGGEST_ENTITY: + case AutocompleteMatchType::SEARCH_SUGGEST_PERSONALIZED: + case AutocompleteMatchType::SEARCH_SUGGEST_PROFILE: + case AutocompleteMatchType::SEARCH_SUGGEST_TAIL: + case AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED: + case AutocompleteMatchType::VOICE_SUGGEST: + return is_incognito ? IDR_IOS_OMNIBOX_SEARCH_INCOGNITO + : IDR_IOS_OMNIBOX_SEARCH; + case AutocompleteMatchType::CALCULATOR: + case AutocompleteMatchType::EXTENSION_APP: + case AutocompleteMatchType::NUM_TYPES: + NOTREACHED(); + return IDR_IOS_OMNIBOX_HTTP; + } +} + +int GetIconForSecurityState( + security_state::SecurityStateModel::SecurityLevel security_level) { + switch (security_level) { + case security_state::SecurityStateModel::NONE: + case security_state::SecurityStateModel::HTTP_SHOW_WARNING: + return IDR_IOS_OMNIBOX_HTTP; + case security_state::SecurityStateModel::EV_SECURE: + case security_state::SecurityStateModel::SECURE: + return IDR_IOS_OMNIBOX_HTTPS_VALID; + case security_state::SecurityStateModel::SECURITY_WARNING: + // Surface Dubious as Neutral. + return IDR_IOS_OMNIBOX_HTTP; + case security_state::SecurityStateModel::SECURE_WITH_POLICY_INSTALLED_CERT: + return IDR_IOS_OMNIBOX_HTTPS_POLICY_WARNING; + case security_state::SecurityStateModel::DANGEROUS: + return IDR_IOS_OMNIBOX_HTTPS_INVALID; + } +}
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_util.h b/ios/chrome/browser/ui/omnibox/omnibox_util.h new file mode 100644 index 0000000..67cc317 --- /dev/null +++ b/ios/chrome/browser/ui/omnibox/omnibox_util.h
@@ -0,0 +1,22 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_UTIL_H_ +#define IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_UTIL_H_ + +#include "components/omnibox/browser/autocomplete_match_type.h" +#include "components/security_state/security_state_model.h" + +// Converts |type| to a resource identifier for the appropriate icon for this +// type to show in the omnibox. +int GetIconForAutocompleteMatchType(AutocompleteMatchType::Type type, + bool is_starred, + bool is_incognito); + +// Converts |security_level| to a resource identifier for the appropriate icon +// for this security level in the omnibox. +int GetIconForSecurityState( + security_state::SecurityStateModel::SecurityLevel security_level); + +#endif // IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_UTIL_H_
diff --git a/media/base/decode_status.h b/media/base/decode_status.h index 790eb5ff..665a9bd5 100644 --- a/media/base/decode_status.h +++ b/media/base/decode_status.h
@@ -16,6 +16,7 @@ ABORTED, // Read aborted due to Reset() during pending read. DECODE_ERROR, // Decoder returned decode error. Note: Prefixed by DECODE_ // since ERROR is a reserved name (special macro) on Windows. + DECODE_STATUS_MAX = DECODE_ERROR }; // Helper function so that DecodeStatus can be printed easily.
diff --git a/media/base/ipc/media_param_traits_macros.h b/media/base/ipc/media_param_traits_macros.h index 38a4c000..31362e2 100644 --- a/media/base/ipc/media_param_traits_macros.h +++ b/media/base/ipc/media_param_traits_macros.h
@@ -8,6 +8,7 @@ #include "ipc/ipc_message_macros.h" #include "media/base/audio_parameters.h" #include "media/base/buffering_state.h" +#include "media/base/decode_status.h" #include "media/base/subsample_entry.h" #include "media/base/video_capture_types.h" #include "media/base/video_types.h" @@ -21,6 +22,9 @@ IPC_ENUM_TRAITS_MAX_VALUE(media::BufferingState, media::BufferingState::BUFFERING_STATE_MAX) +IPC_ENUM_TRAITS_MAX_VALUE(media::DecodeStatus, + media::DecodeStatus::DECODE_STATUS_MAX) + IPC_ENUM_TRAITS_MAX_VALUE(media::ChannelLayout, media::CHANNEL_LAYOUT_MAX) IPC_ENUM_TRAITS_MAX_VALUE(media::VideoPixelFormat, media::PIXEL_FORMAT_MAX)
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 2bdca12..f9ade75b 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -168,4 +168,10 @@ const base::Feature kExternalClearKeyForTesting{ "external-clear-key-for-testing", base::FEATURE_DISABLED_BY_DEFAULT}; +#if defined(OS_ANDROID) +// Replaces WPMA by the MediaPlayerRenderer for HLS and fallback playback. +const base::Feature kAndroidMediaPlayerRenderer{ + "android-media-player-renderer", base::FEATURE_DISABLED_BY_DEFAULT}; +#endif + } // namespace media
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index a5fe588..b1ed8408 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -88,6 +88,9 @@ MEDIA_EXPORT extern const base::Feature kVideoColorManagement; MEDIA_EXPORT extern const base::Feature kExternalClearKeyForTesting; +#if defined(OS_ANDROID) +MEDIA_EXPORT extern const base::Feature kAndroidMediaPlayerRenderer; +#endif // defined(OS_ANDROID) } // namespace media #endif // MEDIA_BASE_MEDIA_SWITCHES_H_
diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc index 5d8aaa3..b52c64df 100644 --- a/media/base/pipeline_impl.cc +++ b/media/base/pipeline_impl.cc
@@ -823,10 +823,24 @@ const PipelineStatusCB& done_cb) { DCHECK(media_task_runner_->BelongsToCurrentThread()); - if (!demuxer_->GetStream(DemuxerStream::AUDIO) && - !demuxer_->GetStream(DemuxerStream::VIDEO)) { - done_cb.Run(PIPELINE_ERROR_COULD_NOT_RENDER); - return; + switch (demuxer_->GetType()) { + case DemuxerStreamProvider::Type::STREAM: + if (!demuxer_->GetStream(DemuxerStream::AUDIO) && + !demuxer_->GetStream(DemuxerStream::VIDEO)) { + DVLOG(1) << "Error: demuxer does not have an audio or a video stream."; + done_cb.Run(PIPELINE_ERROR_COULD_NOT_RENDER); + return; + } + break; + + case DemuxerStreamProvider::Type::URL: + // NOTE: Empty GURL are not valid. + if (!demuxer_->GetUrl().is_valid()) { + DVLOG(1) << "Error: demuxer does not have a valid URL."; + done_cb.Run(PIPELINE_ERROR_COULD_NOT_RENDER); + return; + } + break; } if (cdm_context_) @@ -852,18 +866,31 @@ DCHECK(media_task_runner_->BelongsToCurrentThread()); PipelineMetadata metadata; - metadata.timeline_offset = demuxer_->GetTimelineOffset(); - DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO); - if (stream) { - metadata.has_video = true; - metadata.natural_size = stream->video_decoder_config().natural_size(); - metadata.video_rotation = stream->video_rotation(); - metadata.video_decoder_config = stream->video_decoder_config(); - } - stream = demuxer_->GetStream(DemuxerStream::AUDIO); - if (stream) { - metadata.has_audio = true; - metadata.audio_decoder_config = stream->audio_decoder_config(); + DemuxerStream* stream; + + switch (demuxer_->GetType()) { + case DemuxerStreamProvider::Type::STREAM: + metadata.timeline_offset = demuxer_->GetTimelineOffset(); + stream = demuxer_->GetStream(DemuxerStream::VIDEO); + if (stream) { + metadata.has_video = true; + metadata.natural_size = stream->video_decoder_config().natural_size(); + metadata.video_rotation = stream->video_rotation(); + metadata.video_decoder_config = stream->video_decoder_config(); + } + stream = demuxer_->GetStream(DemuxerStream::AUDIO); + if (stream) { + metadata.has_audio = true; + metadata.audio_decoder_config = stream->audio_decoder_config(); + } + break; + + case DemuxerStreamProvider::Type::URL: + // We don't know if the MediaPlayerRender has Audio/Video until we start + // playing. Conservatively assume that they do. + metadata.has_video = true; + metadata.has_audio = true; + break; } main_task_runner_->PostTask(FROM_HERE, base::Bind(&PipelineImpl::OnMetadata,
diff --git a/media/base/pipeline_metadata.h b/media/base/pipeline_metadata.h index d3030ef..52d037a 100644 --- a/media/base/pipeline_metadata.h +++ b/media/base/pipeline_metadata.h
@@ -22,6 +22,10 @@ // out-of-line copy constructor. PipelineMetadata(const PipelineMetadata&); + // On Android, when using the MediaPlayerRenderer, |has_video| and |has_audio| + // will be true, but the respective configs will be empty. + // Do not make any assumptions on the validity of configs based off of the + // presence of audio/video. bool has_audio; bool has_video; AudioDecoderConfig audio_decoder_config;
diff --git a/media/blink/key_system_config_selector.cc b/media/blink/key_system_config_selector.cc index bbd7c31..dea69d9 100644 --- a/media/blink/key_system_config_selector.cc +++ b/media/blink/key_system_config_selector.cc
@@ -586,6 +586,11 @@ for (size_t i = 0; i < session_types.size(); i++) { // 13.1. Let session type be the value. blink::WebEncryptedMediaSessionType session_type = session_types[i]; + if (session_type == blink::WebEncryptedMediaSessionType::Unknown) { + DVLOG(2) << "Rejecting requested configuration because " + << "session type was not recognized."; + return CONFIGURATION_NOT_SUPPORTED; + } // 13.2. If accumulated configuration's persistentState value is // "not-allowed" and the Is persistent session type? algorithm @@ -604,8 +609,7 @@ EmeConfigRule session_type_rule = EmeConfigRule::NOT_SUPPORTED; switch (session_type) { case blink::WebEncryptedMediaSessionType::Unknown: - DVLOG(2) << "Rejecting requested configuration because " - << "a required session type was not recognized."; + NOTREACHED(); return CONFIGURATION_NOT_SUPPORTED; case blink::WebEncryptedMediaSessionType::Temporary: session_type_rule = EmeConfigRule::SUPPORTED;
diff --git a/media/blink/watch_time_reporter.cc b/media/blink/watch_time_reporter.cc index 5331029..8bb7154 100644 --- a/media/blink/watch_time_reporter.cc +++ b/media/blink/watch_time_reporter.cc
@@ -38,8 +38,6 @@ get_media_time_cb_(get_media_time_cb) { DCHECK(!get_media_time_cb_.is_null()); DCHECK(has_audio_ || has_video_); - if (has_video_) - DCHECK(!initial_video_size_.IsEmpty()); if (base::PowerMonitor* pm = base::PowerMonitor::Get()) pm->AddObserver(this); @@ -120,6 +118,9 @@ bool WatchTimeReporter::ShouldReportWatchTime() { // Only report watch time for media of sufficient size with both audio and // video tracks present. + // TODO(tguilbert): HLS playback will always have an |initial_video_size_| of + // (0,0) and never report watchtime. Fix this as part of HLS UMA cleanup. + // See crbug.com/650891. return has_audio_ && has_video_ && initial_video_size_.height() >= kMinimumVideoSize.height() && initial_video_size_.width() >= kMinimumVideoSize.width();
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 9dea8fb..fdb43c9 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -35,6 +35,7 @@ #include "media/base/media_keys.h" #include "media/base/media_log.h" #include "media/base/media_switches.h" +#include "media/base/media_url_demuxer.h" #include "media/base/text_renderer.h" #include "media/base/timestamp_constants.h" #include "media/base/video_frame.h" @@ -226,6 +227,7 @@ overlay_surface_id_(SurfaceManager::kNoSurfaceID), suppress_destruction_errors_(false), can_suspend_state_(CanSuspendState::UNKNOWN), + use_fallback_path_(false), is_encrypted_(false), underflow_count_(0), observer_(params.media_observer()) { @@ -361,6 +363,9 @@ // Set subresource URL for crash reporting. base::debug::SetCrashKeyValue("subresource_url", gurl.spec()); + if (use_fallback_path_) + fallback_url_ = gurl; + load_type_ = load_type; SetNetworkState(WebMediaPlayer::NetworkStateLoading); @@ -1396,6 +1401,10 @@ void WebMediaPlayerImpl::setPoster(const blink::WebURL& poster) { cast_impl_.setPoster(poster); } + +void WebMediaPlayerImpl::SetUseFallbackPath(bool use_fallback_path) { + use_fallback_path_ = use_fallback_path; +} #endif // defined(OS_ANDROID) // WMPI_CAST void WebMediaPlayerImpl::DataSourceInitialized(bool success) { @@ -1409,7 +1418,7 @@ // // TODO(tguilbert): Remove this code path once we have the ability to host a // MediaPlayer within a Mojo media renderer. http://crbug.com/580626 - if (data_source_) { + if (data_source_ && !use_fallback_path_) { const GURL url_after_redirects = data_source_->GetUrlAfterRedirects(); if (MediaCodecUtil::IsHLSURL(url_after_redirects)) { client_->requestReload(url_after_redirects); @@ -1458,6 +1467,7 @@ const SurfaceCreatedCB& surface_created_cb) { DCHECK(main_task_runner_->BelongsToCurrentThread()); DCHECK(surface_manager_); + DCHECK(!use_fallback_path_); // A null callback indicates that the decoder is going away. if (surface_created_cb.is_null()) { @@ -1505,6 +1515,12 @@ Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb = BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnEncryptedMediaInitData); + if (use_fallback_path_) { + demuxer_.reset(new MediaUrlDemuxer(media_task_runner_, fallback_url_)); + pipeline_controller_.Start(demuxer_.get(), this, false, false); + return; + } + // Figure out which demuxer to use. if (load_type_ != LoadTypeMediaSource) { DCHECK(!chunk_demuxer_);
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h index 9cace20b..729d41e 100644 --- a/media/blink/webmediaplayer_impl.h +++ b/media/blink/webmediaplayer_impl.h
@@ -206,6 +206,7 @@ gfx::Size GetCanvasSize() const; void SetDeviceScaleFactor(float scale_factor); void setPoster(const blink::WebURL& poster) override; + void SetUseFallbackPath(bool use_fallback_path); #endif // Called from WebMediaPlayerCast. @@ -545,6 +546,11 @@ enum class CanSuspendState { UNKNOWN, YES, NO }; CanSuspendState can_suspend_state_; + // Used for HLS playback and in certain fallback paths (e.g. on older devices + // that can't support the unified media pipeline). + GURL fallback_url_; + bool use_fallback_path_; + // Called some-time after OnHidden() if the media was suspended in a playing // state as part of the call to OnHidden(). base::OneShotTimer background_pause_timer_;
diff --git a/media/mojo/clients/mojo_audio_decoder.cc b/media/mojo/clients/mojo_audio_decoder.cc index 0d21183..df2b12a 100644 --- a/media/mojo/clients/mojo_audio_decoder.cc +++ b/media/mojo/clients/mojo_audio_decoder.cc
@@ -175,12 +175,12 @@ base::ResetAndReturn(&init_cb_).Run(success); } -void MojoAudioDecoder::OnDecodeStatus(mojom::DecodeStatus status) { +void MojoAudioDecoder::OnDecodeStatus(DecodeStatus status) { DVLOG(1) << __FUNCTION__ << ": status:" << status; DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(!decode_cb_.is_null()); - base::ResetAndReturn(&decode_cb_).Run(static_cast<DecodeStatus>(status)); + base::ResetAndReturn(&decode_cb_).Run(status); } void MojoAudioDecoder::OnResetDone() {
diff --git a/media/mojo/clients/mojo_audio_decoder.h b/media/mojo/clients/mojo_audio_decoder.h index 14255aa..0d148f8 100644 --- a/media/mojo/clients/mojo_audio_decoder.h +++ b/media/mojo/clients/mojo_audio_decoder.h
@@ -52,7 +52,7 @@ void OnInitialized(bool success, bool needs_bitstream_conversion); // Called when |remote_decoder_| accepted or rejected DecoderBuffer. - void OnDecodeStatus(mojom::DecodeStatus decode_status); + void OnDecodeStatus(DecodeStatus decode_status); // called when |remote_decoder_| finished Reset() sequence. void OnResetDone();
diff --git a/media/mojo/clients/mojo_renderer.cc b/media/mojo/clients/mojo_renderer.cc index f22bfd2b..3f0a7c6 100644 --- a/media/mojo/clients/mojo_renderer.cc +++ b/media/mojo/clients/mojo_renderer.cc
@@ -297,8 +297,10 @@ DVLOG(2) << __FUNCTION__ << ": " << size.ToString(); DCHECK(task_runner_->BelongsToCurrentThread()); - video_renderer_sink_->PaintSingleFrame( - video_overlay_factory_->CreateFrame(size)); + if (video_overlay_factory_) { + video_renderer_sink_->PaintSingleFrame( + video_overlay_factory_->CreateFrame(size)); + } client_->OnVideoNaturalSizeChange(size); }
diff --git a/media/mojo/clients/mojo_renderer_factory.cc b/media/mojo/clients/mojo_renderer_factory.cc index 750b514..31ba267 100644 --- a/media/mojo/clients/mojo_renderer_factory.cc +++ b/media/mojo/clients/mojo_renderer_factory.cc
@@ -17,7 +17,6 @@ shell::mojom::InterfaceProvider* interface_provider) : get_gpu_factories_cb_(get_gpu_factories_cb), interface_provider_(interface_provider) { - DCHECK(!get_gpu_factories_cb_.is_null()); DCHECK(interface_provider_); } @@ -29,8 +28,14 @@ AudioRendererSink* /* audio_renderer_sink */, VideoRendererSink* video_renderer_sink, const RequestSurfaceCB& /* request_surface_cb */) { - std::unique_ptr<VideoOverlayFactory> overlay_factory( - new VideoOverlayFactory(get_gpu_factories_cb_.Run())); + std::unique_ptr<VideoOverlayFactory> overlay_factory; + + // |get_gpu_factories_cb_| can be null in the HLS/MediaPlayerRenderer case, + // when we do not need to create video overlays. + if (!get_gpu_factories_cb_.is_null()) { + overlay_factory = + base::MakeUnique<VideoOverlayFactory>(get_gpu_factories_cb_.Run()); + } mojom::RendererPtr renderer_ptr; shell::GetInterface<mojom::Renderer>(interface_provider_, &renderer_ptr);
diff --git a/media/mojo/clients/mojo_video_decoder.cc b/media/mojo/clients/mojo_video_decoder.cc index 3eb07a77..ee293e6 100644 --- a/media/mojo/clients/mojo_video_decoder.cc +++ b/media/mojo/clients/mojo_video_decoder.cc
@@ -102,10 +102,10 @@ output_cb_.Run(frame.To<scoped_refptr<VideoFrame>>()); } -void MojoVideoDecoder::OnDecodeDone(mojom::DecodeStatus status) { +void MojoVideoDecoder::OnDecodeDone(DecodeStatus status) { DVLOG(1) << __FUNCTION__; DCHECK(task_runner_->BelongsToCurrentThread()); - base::ResetAndReturn(&decode_cb_).Run(static_cast<DecodeStatus>(status)); + base::ResetAndReturn(&decode_cb_).Run(status); } void MojoVideoDecoder::Reset(const base::Closure& reset_cb) {
diff --git a/media/mojo/clients/mojo_video_decoder.h b/media/mojo/clients/mojo_video_decoder.h index 9b08536..1c0facc0 100644 --- a/media/mojo/clients/mojo_video_decoder.h +++ b/media/mojo/clients/mojo_video_decoder.h
@@ -51,7 +51,7 @@ private: void OnInitializeDone(bool status); - void OnDecodeDone(mojom::DecodeStatus status); + void OnDecodeDone(DecodeStatus status); void OnResetDone(); void BindRemoteDecoder();
diff --git a/media/mojo/common/media_type_converters.cc b/media/mojo/common/media_type_converters.cc index 41cc5f40..5ac4b4be1 100644 --- a/media/mojo/common/media_type_converters.cc +++ b/media/mojo/common/media_type_converters.cc
@@ -41,17 +41,6 @@ media::mojom::mojo_enum_value), \ "Mismatched enum: " #media_enum_value " != " #mojo_enum_value) -#define ASSERT_ENUM_CLASS_EQ(media_enum, value) \ - static_assert( \ - media::media_enum::value == \ - static_cast<media::media_enum>(media::mojom::media_enum::value), \ - "Mismatched enum: " #media_enum #value) - -// DecodeStatus. -ASSERT_ENUM_CLASS_EQ(DecodeStatus, OK); -ASSERT_ENUM_CLASS_EQ(DecodeStatus, ABORTED); -ASSERT_ENUM_CLASS_EQ(DecodeStatus, DECODE_ERROR); - // AudioCodec. ASSERT_ENUM_EQ_RAW(AudioCodec, kUnknownAudioCodec, AudioCodec::UNKNOWN); ASSERT_ENUM_EQ(AudioCodec, kCodec, , AAC);
diff --git a/media/mojo/interfaces/media_types.mojom b/media/mojo/interfaces/media_types.mojom index c223d113..76fe936 100644 --- a/media/mojo/interfaces/media_types.mojom +++ b/media/mojo/interfaces/media_types.mojom
@@ -12,12 +12,8 @@ enum BufferingState; // See media/base/decode_status.h for descriptions. -// Kept in sync with media::DecodeStatus via static_asserts. -enum DecodeStatus { - OK, - ABORTED, - DECODE_ERROR, -}; +[Native] +enum DecodeStatus; // See media/base/audio_decoder_config.h for descriptions. // Kept in sync with media::AudioCodec via static_asserts.
diff --git a/media/mojo/interfaces/media_types.typemap b/media/mojo/interfaces/media_types.typemap index b6a56ec..a135b825 100644 --- a/media/mojo/interfaces/media_types.typemap +++ b/media/mojo/interfaces/media_types.typemap
@@ -6,6 +6,7 @@ public_headers = [ "//media/base/buffering_state.h", + "//media/base/decode_status.h", "//media/base/subsample_entry.h", ] @@ -18,5 +19,6 @@ type_mappings = [ "media.mojom.BufferingState=media::BufferingState", + "media.mojom.DecodeStatus=media::DecodeStatus", "media.mojom.SubsampleEntry=media::SubsampleEntry", ]
diff --git a/media/mojo/services/mojo_audio_decoder_service.cc b/media/mojo/services/mojo_audio_decoder_service.cc index 0e0fd15..039cb5d 100644 --- a/media/mojo/services/mojo_audio_decoder_service.cc +++ b/media/mojo/services/mojo_audio_decoder_service.cc
@@ -83,7 +83,7 @@ scoped_refptr<DecoderBuffer> media_buffer = mojo_decoder_buffer_reader_->ReadDecoderBuffer(buffer); if (!media_buffer) { - callback.Run(mojom::DecodeStatus::DECODE_ERROR); + callback.Run(DecodeStatus::DECODE_ERROR); return; } @@ -112,10 +112,14 @@ } } +// These two methods are needed so that we can bind them with a weak pointer to +// avoid running the |callback| after connection error happens and |this| is +// deleted. It's not safe to run the |callback| after a connection error. + void MojoAudioDecoderService::OnDecodeStatus(const DecodeCallback& callback, media::DecodeStatus status) { DVLOG(3) << __FUNCTION__ << " status:" << status; - callback.Run(static_cast<mojom::DecodeStatus>(status)); + callback.Run(status); } void MojoAudioDecoderService::OnResetDone(const ResetCallback& callback) {
diff --git a/media/mojo/services/mojo_video_decoder_service.cc b/media/mojo/services/mojo_video_decoder_service.cc index a535f60..0150f0d 100644 --- a/media/mojo/services/mojo_video_decoder_service.cc +++ b/media/mojo/services/mojo_video_decoder_service.cc
@@ -64,26 +64,12 @@ base::Bind(&MojoVideoDecoderService::OnDecoderOutput, weak_this_)); } -void MojoVideoDecoderService::OnDecoderInitialized( - const InitializeCallback& callback, - bool success) { - DVLOG(1) << __FUNCTION__; - callback.Run(success); -} - -void MojoVideoDecoderService::OnDecoderOutput( - const scoped_refptr<VideoFrame>& frame) { - DVLOG(1) << __FUNCTION__; - DCHECK(client_); - client_->OnVideoFrameDecoded(mojom::VideoFrame::From(frame)); -} - void MojoVideoDecoderService::Decode(mojom::DecoderBufferPtr buffer, const DecodeCallback& callback) { DVLOG(1) << __FUNCTION__; if (!decoder_) { - callback.Run(mojom::DecodeStatus::DECODE_ERROR); + callback.Run(DecodeStatus::DECODE_ERROR); return; } @@ -92,7 +78,7 @@ scoped_refptr<DecoderBuffer> media_buffer = mojo_decoder_buffer_reader_->ReadDecoderBuffer(buffer); if (!media_buffer) { - callback.Run(mojom::DecodeStatus::DECODE_ERROR); + callback.Run(DecodeStatus::DECODE_ERROR); return; } @@ -101,12 +87,6 @@ weak_this_, callback)); } -void MojoVideoDecoderService::OnDecoderDecoded(const DecodeCallback& callback, - DecodeStatus status) { - DVLOG(1) << __FUNCTION__; - callback.Run(static_cast<mojom::DecodeStatus>(status)); -} - void MojoVideoDecoderService::Reset(const ResetCallback& callback) { DVLOG(1) << __FUNCTION__; @@ -119,9 +99,29 @@ weak_this_, callback)); } +void MojoVideoDecoderService::OnDecoderInitialized( + const InitializeCallback& callback, + bool success) { + DVLOG(1) << __FUNCTION__; + callback.Run(success); +} + +void MojoVideoDecoderService::OnDecoderDecoded(const DecodeCallback& callback, + DecodeStatus status) { + DVLOG(1) << __FUNCTION__; + callback.Run(status); +} + void MojoVideoDecoderService::OnDecoderReset(const ResetCallback& callback) { DVLOG(1) << __FUNCTION__; callback.Run(); } +void MojoVideoDecoderService::OnDecoderOutput( + const scoped_refptr<VideoFrame>& frame) { + DVLOG(1) << __FUNCTION__; + DCHECK(client_); + client_->OnVideoFrameDecoded(mojom::VideoFrame::From(frame)); +} + } // namespace media
diff --git a/media/mojo/services/mojo_video_decoder_service.h b/media/mojo/services/mojo_video_decoder_service.h index 89836b4..bbb16cd 100644 --- a/media/mojo/services/mojo_video_decoder_service.h +++ b/media/mojo/services/mojo_video_decoder_service.h
@@ -37,11 +37,16 @@ void Reset(const ResetCallback& callback) final; private: + // Helper methods so that we can bind them with a weak pointer to avoid + // running mojom::VideoDecoder callbacks after connection error happens and + // |this| is deleted. It's not safe to run the callbacks after a connection + // error. void OnDecoderInitialized(const InitializeCallback& callback, bool success); void OnDecoderDecoded(const DecodeCallback& callback, DecodeStatus status); - void OnDecoderOutput(const scoped_refptr<VideoFrame>& frame); void OnDecoderReset(const ResetCallback& callback); + void OnDecoderOutput(const scoped_refptr<VideoFrame>& frame); + mojom::VideoDecoderClientAssociatedPtr client_; std::unique_ptr<MojoDecoderBufferReader> mojo_decoder_buffer_reader_;
diff --git a/media/remoting/remoting_controller.cc b/media/remoting/remoting_controller.cc index 3d976da..dd38d70 100644 --- a/media/remoting/remoting_controller.cc +++ b/media/remoting/remoting_controller.cc
@@ -103,13 +103,14 @@ if (!has_video_ && !has_audio_) return; + // On Android, when using the MediaPlayerRenderer, |has_video_| and + // |has_audio_| will be true, but the respective configs will be empty. + // We cannot make any assumptions on the validity of configs. if (has_video_) { - DCHECK(metadata.video_decoder_config.IsValidConfig()); video_decoder_config_ = metadata.video_decoder_config; is_encrypted_ |= video_decoder_config_.is_encrypted(); } if (has_audio_) { - DCHECK(metadata.audio_decoder_config.IsValidConfig()); audio_decoder_config_ = metadata.audio_decoder_config; is_encrypted_ |= audio_decoder_config_.is_encrypted(); }
diff --git a/media/renderers/gpu_video_accelerator_factories.h b/media/renderers/gpu_video_accelerator_factories.h index f725b73..3c2424d 100644 --- a/media/renderers/gpu_video_accelerator_factories.h +++ b/media/renderers/gpu_video_accelerator_factories.h
@@ -59,6 +59,14 @@ DISALLOW_COPY_AND_ASSIGN(ScopedGLContextLock); }; + enum class OutputFormat { + UNDEFINED = 0, // Unset state + I420, // 3 x R8 GMBs + UYVY, // One 422 GMB + NV12_SINGLE_GMB, // One NV12 GMB + NV12_DUAL_GMB, // One R8, one RG88 GMB + }; + // Return whether GPU encoding/decoding is enabled. virtual bool IsGpuVideoAcceleratorEnabled() = 0; // Caller owns returned pointer, but should call Destroy() on it (instead of @@ -93,7 +101,7 @@ virtual unsigned ImageTextureTarget(gfx::BufferFormat format) = 0; // Pixel format of the hardware video frames created when GpuMemoryBuffers // video frames are enabled. - virtual VideoPixelFormat VideoFrameOutputFormat() = 0; + virtual OutputFormat VideoFrameOutputFormat() = 0; virtual std::unique_ptr<ScopedGLContextLock> GetGLContextLock() = 0;
diff --git a/media/renderers/mock_gpu_video_accelerator_factories.cc b/media/renderers/mock_gpu_video_accelerator_factories.cc index afc5d9f..854eb2e 100644 --- a/media/renderers/mock_gpu_video_accelerator_factories.cc +++ b/media/renderers/mock_gpu_video_accelerator_factories.cc
@@ -23,6 +23,7 @@ num_planes_(gfx::NumberOfPlanesForBufferFormat(format)), id_(g_next_gpu_memory_buffer_id++) { DCHECK(gfx::BufferFormat::R_8 == format_ || + gfx::BufferFormat::RG_88 == format_ || gfx::BufferFormat::YUV_420_BIPLANAR == format_ || gfx::BufferFormat::UYVY_422 == format_); DCHECK(num_planes_ <= kMaxPlanes);
diff --git a/media/renderers/mock_gpu_video_accelerator_factories.h b/media/renderers/mock_gpu_video_accelerator_factories.h index 3337bca..6aec6b1e 100644 --- a/media/renderers/mock_gpu_video_accelerator_factories.h +++ b/media/renderers/mock_gpu_video_accelerator_factories.h
@@ -57,15 +57,14 @@ bool ShouldUseGpuMemoryBuffersForVideoFrames() const override; unsigned ImageTextureTarget(gfx::BufferFormat format) override; - VideoPixelFormat VideoFrameOutputFormat() override { + OutputFormat VideoFrameOutputFormat() override { return video_frame_output_format_; }; std::unique_ptr<GpuVideoAcceleratorFactories::ScopedGLContextLock> GetGLContextLock() override; - void SetVideoFrameOutputFormat( - const VideoPixelFormat video_frame_output_format) { + void SetVideoFrameOutputFormat(const OutputFormat video_frame_output_format) { video_frame_output_format_ = video_frame_output_format; }; @@ -89,7 +88,7 @@ DISALLOW_COPY_AND_ASSIGN(MockGpuVideoAcceleratorFactories); base::Lock lock_; - VideoPixelFormat video_frame_output_format_ = PIXEL_FORMAT_I420; + OutputFormat video_frame_output_format_ = OutputFormat::I420; bool fail_to_allocate_gpu_memory_buffer_ = false;
diff --git a/media/video/gpu_memory_buffer_video_frame_pool.cc b/media/video/gpu_memory_buffer_video_frame_pool.cc index 4b2f7a1b6b..2b4d5d4b 100644 --- a/media/video/gpu_memory_buffer_video_frame_pool.cc +++ b/media/video/gpu_memory_buffer_video_frame_pool.cc
@@ -53,7 +53,7 @@ : media_task_runner_(media_task_runner), worker_task_runner_(worker_task_runner), gpu_factories_(gpu_factories), - output_format_(PIXEL_FORMAT_UNKNOWN) { + output_format_(GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED) { DCHECK(media_task_runner_); DCHECK(worker_task_runner_); } @@ -128,8 +128,9 @@ // Get the resources needed for a frame out of the pool, or create them if // necessary. // This also drops the LRU resources that can't be reuse for this frame. - FrameResources* GetOrCreateFrameResources(const gfx::Size& size, - VideoPixelFormat format); + FrameResources* GetOrCreateFrameResources( + const gfx::Size& size, + GpuVideoAcceleratorFactories::OutputFormat format); // Callback called when a VideoFrame generated with GetFrameResources is no // longer referenced. @@ -153,9 +154,7 @@ // Pool of resources. std::list<FrameResources*> resources_pool_; - // TODO(dcastagna): change the following type from VideoPixelFormat to - // BufferFormat. - VideoPixelFormat output_format_; + GpuVideoAcceleratorFactories::OutputFormat output_format_; DISALLOW_COPY_AND_ASSIGN(PoolImpl); }; @@ -168,52 +167,95 @@ // Return the GpuMemoryBuffer format to use for a specific VideoPixelFormat // and plane. -gfx::BufferFormat GpuMemoryBufferFormat(VideoPixelFormat format, size_t plane) { +gfx::BufferFormat GpuMemoryBufferFormat( + media::GpuVideoAcceleratorFactories::OutputFormat format, + size_t plane) { switch (format) { - case PIXEL_FORMAT_I420: + case GpuVideoAcceleratorFactories::OutputFormat::I420: DCHECK_LE(plane, 2u); return gfx::BufferFormat::R_8; - case PIXEL_FORMAT_NV12: + case GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB: DCHECK_LE(plane, 1u); return gfx::BufferFormat::YUV_420_BIPLANAR; - case PIXEL_FORMAT_UYVY: + case GpuVideoAcceleratorFactories::OutputFormat::NV12_DUAL_GMB: + DCHECK_LE(plane, 1u); + return plane == 0 ? gfx::BufferFormat::R_8 : gfx::BufferFormat::RG_88; + case GpuVideoAcceleratorFactories::OutputFormat::UYVY: DCHECK_EQ(0u, plane); return gfx::BufferFormat::UYVY_422; - default: + case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED: NOTREACHED(); - return gfx::BufferFormat::BGRA_8888; + break; } + return gfx::BufferFormat::BGRA_8888; } -unsigned ImageInternalFormat(VideoPixelFormat format, size_t plane) { +unsigned ImageInternalFormat(GpuVideoAcceleratorFactories::OutputFormat format, + size_t plane) { switch (format) { - case PIXEL_FORMAT_I420: + case GpuVideoAcceleratorFactories::OutputFormat::I420: DCHECK_LE(plane, 2u); return GL_RED_EXT; - case PIXEL_FORMAT_NV12: + case GpuVideoAcceleratorFactories::OutputFormat::NV12_DUAL_GMB: + DCHECK_LE(plane, 1u); + return plane == 0 ? GL_RED_EXT : GL_RG_EXT; + case GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB: DCHECK_LE(plane, 1u); return GL_RGB_YCBCR_420V_CHROMIUM; - case PIXEL_FORMAT_UYVY: + case GpuVideoAcceleratorFactories::OutputFormat::UYVY: DCHECK_EQ(0u, plane); return GL_RGB_YCBCR_422_CHROMIUM; - default: + case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED: NOTREACHED(); - return 0; + break; } + return 0; } // The number of output planes to be copied in each iteration. -size_t PlanesPerCopy(VideoPixelFormat format) { +size_t PlanesPerCopy(GpuVideoAcceleratorFactories::OutputFormat format) { switch (format) { - case PIXEL_FORMAT_I420: - case PIXEL_FORMAT_UYVY: + case GpuVideoAcceleratorFactories::OutputFormat::I420: + case GpuVideoAcceleratorFactories::OutputFormat::UYVY: return 1; - case PIXEL_FORMAT_NV12: + case GpuVideoAcceleratorFactories::OutputFormat::NV12_DUAL_GMB: + case GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB: return 2; - default: + case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED: NOTREACHED(); - return 0; + break; } + return 0; +} + +VideoPixelFormat VideoFormat( + GpuVideoAcceleratorFactories::OutputFormat format) { + switch (format) { + case GpuVideoAcceleratorFactories::OutputFormat::I420: + return PIXEL_FORMAT_I420; + case GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB: + case GpuVideoAcceleratorFactories::OutputFormat::NV12_DUAL_GMB: + return PIXEL_FORMAT_NV12; + case GpuVideoAcceleratorFactories::OutputFormat::UYVY: + return PIXEL_FORMAT_UYVY; + case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED: + NOTREACHED(); + break; + } + return PIXEL_FORMAT_UNKNOWN; +} + +VideoPixelFormat FinalVideoFormat( + GpuVideoAcceleratorFactories::OutputFormat format) { + // Consumers should sample from NV12 textures as if they're XRGB. + if (format == GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB) + return PIXEL_FORMAT_XRGB; + return VideoFormat(format); +} + +// The number of output planes to be copied in each iteration. +size_t NumGpuMemoryBuffers(GpuVideoAcceleratorFactories::OutputFormat format) { + return VideoFrame::NumPlanes(FinalVideoFormat(format)); } // The number of output rows to be copied in each iteration. @@ -313,23 +355,24 @@ } gfx::Size CodedSize(const scoped_refptr<VideoFrame>& video_frame, - VideoPixelFormat output_format) { + GpuVideoAcceleratorFactories::OutputFormat output_format) { DCHECK(gfx::Rect(video_frame->coded_size()) .Contains(video_frame->visible_rect())); DCHECK((video_frame->visible_rect().x() & 1) == 0); gfx::Size output; switch (output_format) { - case PIXEL_FORMAT_I420: - case PIXEL_FORMAT_NV12: + case GpuVideoAcceleratorFactories::OutputFormat::I420: + case GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB: + case GpuVideoAcceleratorFactories::OutputFormat::NV12_DUAL_GMB: DCHECK((video_frame->visible_rect().y() & 1) == 0); output = gfx::Size((video_frame->visible_rect().width() + 1) & ~1, (video_frame->visible_rect().height() + 1) & ~1); break; - case PIXEL_FORMAT_UYVY: + case GpuVideoAcceleratorFactories::OutputFormat::UYVY: output = gfx::Size((video_frame->visible_rect().width() + 1) & ~1, video_frame->visible_rect().height()); break; - default: + case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED: NOTREACHED(); } DCHECK(gfx::Rect(video_frame->coded_size()).Contains(gfx::Rect(output))); @@ -348,10 +391,10 @@ DCHECK(media_task_runner_->BelongsToCurrentThread()); // Lazily initialize output_format_ since VideoFrameOutputFormat() has to be // called on the media_thread while this object might be instantiated on any. - if (output_format_ == PIXEL_FORMAT_UNKNOWN) + if (output_format_ == GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED) output_format_ = gpu_factories_->VideoFrameOutputFormat(); - if (output_format_ == PIXEL_FORMAT_UNKNOWN) { + if (output_format_ == GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED) { frame_ready_cb.Run(video_frame); return; } @@ -466,25 +509,27 @@ FrameResources* frame_resources, const FrameReadyCB& frame_ready_cb) { // Compute the number of tasks to post and create the barrier. - const size_t num_planes = VideoFrame::NumPlanes(output_format_); + const size_t num_planes = VideoFrame::NumPlanes(VideoFormat(output_format_)); const size_t planes_per_copy = PlanesPerCopy(output_format_); const gfx::Size coded_size = CodedSize(video_frame, output_format_); size_t copies = 0; for (size_t i = 0; i < num_planes; i += planes_per_copy) { - const int rows = VideoFrame::Rows(i, output_format_, coded_size.height()); + const int rows = + VideoFrame::Rows(i, VideoFormat(output_format_), coded_size.height()); const int rows_per_copy = - RowsPerCopy(i, output_format_, coded_size.width()); + RowsPerCopy(i, VideoFormat(output_format_), coded_size.width()); copies += rows / rows_per_copy; if (rows % rows_per_copy) ++copies; } + const base::Closure copies_done = base::Bind(&PoolImpl::OnCopiesDone, this, video_frame, frame_resources, frame_ready_cb); const base::Closure barrier = base::BarrierClosure(copies, copies_done); - // Post all the async tasks. - for (size_t i = 0; i < num_planes; i += planes_per_copy) { + // Map the buffers. + for (size_t i = 0; i < NumGpuMemoryBuffers(output_format_); i++) { gfx::GpuMemoryBuffer* buffer = frame_resources->plane_resources[i].gpu_memory_buffer.get(); @@ -492,19 +537,23 @@ DLOG(ERROR) << "Could not get or Map() buffer"; return; } - DCHECK_EQ(planes_per_copy, - gfx::NumberOfPlanesForBufferFormat(buffer->GetFormat())); + } - const int rows = VideoFrame::Rows(i, output_format_, coded_size.height()); + // Post all the async tasks. + for (size_t i = 0; i < num_planes; i += planes_per_copy) { + gfx::GpuMemoryBuffer* buffer = + frame_resources->plane_resources[i].gpu_memory_buffer.get(); + const int rows = + VideoFrame::Rows(i, VideoFormat(output_format_), coded_size.height()); const int rows_per_copy = - RowsPerCopy(i, output_format_, coded_size.width()); + RowsPerCopy(i, VideoFormat(output_format_), coded_size.width()); for (int row = 0; row < rows; row += rows_per_copy) { const int rows_to_copy = std::min(rows_per_copy, rows - row); switch (output_format_) { - case PIXEL_FORMAT_I420: { - const int bytes_per_row = - VideoFrame::RowBytes(i, output_format_, coded_size.width()); + case GpuVideoAcceleratorFactories::OutputFormat::I420: { + const int bytes_per_row = VideoFrame::RowBytes( + i, VideoFormat(output_format_), coded_size.width()); worker_task_runner_->PostTask( FROM_HERE, base::Bind(&CopyRowsToI420Buffer, row, rows_to_copy, bytes_per_row, video_frame->visible_data(i), @@ -513,7 +562,7 @@ buffer->stride(0), barrier)); break; } - case PIXEL_FORMAT_NV12: + case GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB: worker_task_runner_->PostTask( FROM_HERE, base::Bind(&CopyRowsToNV12Buffer, row, rows_to_copy, coded_size.width(), video_frame, @@ -522,14 +571,27 @@ static_cast<uint8_t*>(buffer->memory(1)), buffer->stride(1), barrier)); break; - case PIXEL_FORMAT_UYVY: + case GpuVideoAcceleratorFactories::OutputFormat::NV12_DUAL_GMB: { + gfx::GpuMemoryBuffer* buffer2 = + frame_resources->plane_resources[1].gpu_memory_buffer.get(); + worker_task_runner_->PostTask( + FROM_HERE, base::Bind(&CopyRowsToNV12Buffer, row, rows_to_copy, + coded_size.width(), video_frame, + static_cast<uint8_t*>(buffer->memory(0)), + buffer->stride(0), + static_cast<uint8_t*>(buffer2->memory(0)), + buffer2->stride(0), barrier)); + break; + } + + case GpuVideoAcceleratorFactories::OutputFormat::UYVY: worker_task_runner_->PostTask( FROM_HERE, base::Bind(&CopyRowsToUYVYBuffer, row, rows_to_copy, coded_size.width(), video_frame, static_cast<uint8_t*>(buffer->memory(0)), buffer->stride(0), barrier)); break; - default: + case GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED: NOTREACHED(); } } @@ -549,24 +611,21 @@ } gpu::gles2::GLES2Interface* gles2 = lock->ContextGL(); - const size_t num_planes = VideoFrame::NumPlanes(output_format_); - const size_t planes_per_copy = PlanesPerCopy(output_format_); const gfx::Size coded_size = CodedSize(video_frame, output_format_); gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes]; // Set up the planes creating the mailboxes needed to refer to the textures. - for (size_t i = 0; i < num_planes; i += planes_per_copy) { + for (size_t i = 0; i < NumGpuMemoryBuffers(output_format_); i++) { PlaneResource& plane_resource = frame_resources->plane_resources[i]; const gfx::BufferFormat buffer_format = GpuMemoryBufferFormat(output_format_, i); unsigned texture_target = gpu_factories_->ImageTextureTarget(buffer_format); // Bind the texture and create or rebind the image. gles2->BindTexture(texture_target, plane_resource.texture_id); - if (plane_resource.gpu_memory_buffer && !plane_resource.image_id) { - const size_t width = - VideoFrame::Columns(i, output_format_, coded_size.width()); + const size_t width = VideoFrame::Columns(i, VideoFormat(output_format_), + coded_size.width()); const size_t height = - VideoFrame::Rows(i, output_format_, coded_size.height()); + VideoFrame::Rows(i, VideoFormat(output_format_), coded_size.height()); plane_resource.image_id = gles2->CreateImageCHROMIUM( plane_resource.gpu_memory_buffer->AsClientBuffer(), width, height, ImageInternalFormat(output_format_, i)); @@ -587,17 +646,13 @@ gpu::SyncToken sync_token; gles2->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); - for (size_t i = 0; i < num_planes; i += planes_per_copy) + for (size_t i = 0; i < NumGpuMemoryBuffers(output_format_); i++) mailbox_holders[i].sync_token = sync_token; - auto release_mailbox_callback = BindToCurrentLoop( base::Bind(&PoolImpl::MailboxHoldersReleased, this, frame_resources)); - // Consumers should sample from NV12 textures as if they're XRGB. - VideoPixelFormat frame_format = - output_format_ == PIXEL_FORMAT_NV12 ? PIXEL_FORMAT_XRGB : output_format_; - DCHECK_EQ(VideoFrame::NumPlanes(frame_format) * planes_per_copy, num_planes); + VideoPixelFormat frame_format = FinalVideoFormat(output_format_); // Create the VideoFrame backed by native textures. gfx::Size visible_size = video_frame->visible_rect().size(); @@ -616,12 +671,12 @@ bool allow_overlay = false; switch (output_format_) { - case PIXEL_FORMAT_I420: + case GpuVideoAcceleratorFactories::OutputFormat::I420: allow_overlay = video_frame->metadata()->IsTrue(VideoFrameMetadata::ALLOW_OVERLAY); break; - case PIXEL_FORMAT_NV12: - case PIXEL_FORMAT_UYVY: + case GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB: + case GpuVideoAcceleratorFactories::OutputFormat::UYVY: allow_overlay = true; break; default: @@ -661,7 +716,7 @@ GpuMemoryBufferVideoFramePool::PoolImpl::FrameResources* GpuMemoryBufferVideoFramePool::PoolImpl::GetOrCreateFrameResources( const gfx::Size& size, - VideoPixelFormat format) { + GpuVideoAcceleratorFactories::OutputFormat format) { auto it = resources_pool_.begin(); while (it != resources_pool_.end()) { FrameResources* frame_resources = *it; @@ -687,13 +742,14 @@ gpu::gles2::GLES2Interface* gles2 = lock->ContextGL(); gles2->ActiveTexture(GL_TEXTURE0); - size_t num_planes = VideoFrame::NumPlanes(format); FrameResources* frame_resources = new FrameResources(size); resources_pool_.push_back(frame_resources); - for (size_t i = 0; i < num_planes; i += PlanesPerCopy(format)) { + for (size_t i = 0; i < NumGpuMemoryBuffers(output_format_); i++) { PlaneResource& plane_resource = frame_resources->plane_resources[i]; - const size_t width = VideoFrame::Columns(i, format, size.width()); - const size_t height = VideoFrame::Rows(i, format, size.height()); + const size_t width = + VideoFrame::Columns(i, VideoFormat(format), size.width()); + const size_t height = + VideoFrame::Rows(i, VideoFormat(format), size.height()); plane_resource.size = gfx::Size(width, height); const gfx::BufferFormat buffer_format = GpuMemoryBufferFormat(format, i);
diff --git a/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc b/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc index ea160f0..67ece21 100644 --- a/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc +++ b/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc
@@ -141,7 +141,8 @@ TEST_F(GpuMemoryBufferVideoFramePoolTest, VideoFrameOutputFormatUnknown) { scoped_refptr<VideoFrame> software_frame = CreateTestYUVVideoFrame(10); - mock_gpu_factories_->SetVideoFrameOutputFormat(PIXEL_FORMAT_UNKNOWN); + mock_gpu_factories_->SetVideoFrameOutputFormat( + media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED); scoped_refptr<VideoFrame> frame; gpu_memory_buffer_pool_->MaybeCreateHardwareFrame( software_frame, base::Bind(MaybeCreateHardwareFrameCallback, &frame)); @@ -218,7 +219,8 @@ TEST_F(GpuMemoryBufferVideoFramePoolTest, CreateOneHardwareUYUVFrame) { scoped_refptr<VideoFrame> software_frame = CreateTestYUVVideoFrame(10); scoped_refptr<VideoFrame> frame; - mock_gpu_factories_->SetVideoFrameOutputFormat(PIXEL_FORMAT_UYVY); + mock_gpu_factories_->SetVideoFrameOutputFormat( + media::GpuVideoAcceleratorFactories::OutputFormat::UYVY); gpu_memory_buffer_pool_->MaybeCreateHardwareFrame( software_frame, base::Bind(MaybeCreateHardwareFrameCallback, &frame)); @@ -233,7 +235,8 @@ TEST_F(GpuMemoryBufferVideoFramePoolTest, CreateOneHardwareNV12Frame) { scoped_refptr<VideoFrame> software_frame = CreateTestYUVVideoFrame(10); scoped_refptr<VideoFrame> frame; - mock_gpu_factories_->SetVideoFrameOutputFormat(PIXEL_FORMAT_NV12); + mock_gpu_factories_->SetVideoFrameOutputFormat( + media::GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB); gpu_memory_buffer_pool_->MaybeCreateHardwareFrame( software_frame, base::Bind(MaybeCreateHardwareFrameCallback, &frame)); @@ -245,6 +248,22 @@ media::VideoFrameMetadata::READ_LOCK_FENCES_ENABLED)); } +TEST_F(GpuMemoryBufferVideoFramePoolTest, CreateOneHardwareNV12Frame2) { + scoped_refptr<VideoFrame> software_frame = CreateTestYUVVideoFrame(10); + scoped_refptr<VideoFrame> frame; + mock_gpu_factories_->SetVideoFrameOutputFormat( + media::GpuVideoAcceleratorFactories::OutputFormat::NV12_DUAL_GMB); + gpu_memory_buffer_pool_->MaybeCreateHardwareFrame( + software_frame, base::Bind(MaybeCreateHardwareFrameCallback, &frame)); + + RunUntilIdle(); + + EXPECT_NE(software_frame.get(), frame.get()); + EXPECT_EQ(2u, gles2_->gen_textures); + EXPECT_TRUE(frame->metadata()->IsTrue( + media::VideoFrameMetadata::READ_LOCK_FENCES_ENABLED)); +} + // AllocateGpuMemoryBuffer can return null (e.g: when the GPU process is down). // This test checks that in that case we don't crash and still create the // textures.
diff --git a/native_client_sdk/src/libraries/nacl_io/BUILD.gn b/native_client_sdk/src/libraries/nacl_io/BUILD.gn index 7b401f8..a8cf833 100644 --- a/native_client_sdk/src/libraries/nacl_io/BUILD.gn +++ b/native_client_sdk/src/libraries/nacl_io/BUILD.gn
@@ -32,6 +32,7 @@ "fusefs/fuse_fs_factory.cc", "getdents_helper.cc", "h_errno.c", + "hash.cc", "host_resolver.cc", "html5fs/html5_fs.cc", "html5fs/html5_fs_node.cc",
diff --git a/native_client_sdk/src/libraries/nacl_io/hash.cc b/native_client_sdk/src/libraries/nacl_io/hash.cc new file mode 100644 index 0000000..6293fae --- /dev/null +++ b/native_client_sdk/src/libraries/nacl_io/hash.cc
@@ -0,0 +1,31 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "nacl_io/hash.h" +#include "nacl_io/osdirent.h" + +namespace nacl_io { + +ino_t HashPathSegment(ino_t hash, const char* str, size_t len) { + // First add the path seperator + hash = (hash * static_cast<ino_t>(33)) ^ '/'; + while (len--) { + hash = (hash * static_cast<ino_t>(33)) ^ *str++; + } + return hash; +} + +ino_t HashPath(const Path& path) { + // Prime the DJB2a hash + ino_t hash = 5381; + + // Apply a running DJB2a to each part of the path + for (size_t segment = 0; segment < path.Size(); segment++) { + const std::string& part = path.Part(segment); + hash = HashPathSegment(hash, part.c_str(), part.length()); + } + return hash; +} + +} // namespace nacl_io
diff --git a/native_client_sdk/src/libraries/nacl_io/hash.h b/native_client_sdk/src/libraries/nacl_io/hash.h new file mode 100644 index 0000000..b2589c08 --- /dev/null +++ b/native_client_sdk/src/libraries/nacl_io/hash.h
@@ -0,0 +1,18 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef LIBRARIES_NACL_IO_HASH_H_ +#define LIBRARIES_NACL_IO_HASH_H_ + +#include "nacl_io/osdirent.h" +#include "nacl_io/path.h" + +namespace nacl_io { + +ino_t HashPathSegment(ino_t hash, const char* str, size_t len); +ino_t HashPath(const Path& path); + +} // namespace nacl_io + +#endif // LIBRARIES_NACL_IO_HASH_H_
diff --git a/native_client_sdk/src/libraries/nacl_io/html5fs/html5_fs.cc b/native_client_sdk/src/libraries/nacl_io/html5fs/html5_fs.cc index 954d8e36..61fe45b 100644 --- a/native_client_sdk/src/libraries/nacl_io/html5fs/html5_fs.cc +++ b/native_client_sdk/src/libraries/nacl_io/html5fs/html5_fs.cc
@@ -14,6 +14,7 @@ #include <ppapi/c/pp_completion_callback.h> #include <ppapi/c/pp_errors.h> +#include "nacl_io/hash.h" #include "nacl_io/html5fs/html5_fs_node.h" #include "sdk_util/auto_lock.h" @@ -29,29 +30,6 @@ } // namespace -// Continuing DJB2a hash -ino_t Html5Fs::HashPathSegment(ino_t hash, const char *str, size_t len) { - // First add the path seperator - hash = (hash * static_cast<ino_t>(33)) ^ '/'; - while (len--) { - hash = (hash * static_cast<ino_t>(33)) ^ *str++; - } - return hash; -} - -ino_t Html5Fs::HashPath(const Path& path) { - // Prime the DJB2a hash - ino_t hash = 5381; - - // Apply a running DJB2a to each part of the path - for (size_t segment = 0; segment < path.Size(); segment++) { - const std::string& part = path.Part(segment); - hash = HashPathSegment(hash, part.c_str(), part.length()); - } - return hash; -} - - // For HTML5, the INO should be the one used by the system, however PPAPI // does not provide access to the real INO. Instead, since HTML5 does not // suport links, we assume that files are unique based on path to the base @@ -62,8 +40,9 @@ void Html5Fs::OnNodeDestroyed(Node* node) {} - -Error Html5Fs::OpenWithMode(const Path& path, int open_flags, mode_t mode, +Error Html5Fs::OpenWithMode(const Path& path, + int open_flags, + mode_t mode, ScopedNode* out_node) { out_node->reset(NULL); Error error = BlockUntilFilesystemOpen(); @@ -114,9 +93,8 @@ return EEXIST; ScopedResource fileref_resource( - ppapi(), - file_ref_iface_->Create(filesystem_resource_, - GetFullPath(path).Join().c_str())); + ppapi(), file_ref_iface_->Create(filesystem_resource_, + GetFullPath(path).Join().c_str())); if (!fileref_resource.pp_resource()) return ENOENT; @@ -142,9 +120,8 @@ return error; ScopedResource fileref_resource( - ppapi(), - file_ref_iface_->Create(filesystem_resource_, - GetFullPath(path).Join().c_str())); + ppapi(), file_ref_iface_->Create(filesystem_resource_, + GetFullPath(path).Join().c_str())); if (!fileref_resource.pp_resource()) return ENOENT; @@ -217,8 +194,7 @@ file_io_iface_(NULL), filesystem_resource_(0), filesystem_open_has_result_(false), - filesystem_open_error_(0) { -} + filesystem_open_error_(0) {} Error Html5Fs::Init(const FsInitArgs& args) { pthread_cond_init(&filesystem_open_cond_, NULL); @@ -239,8 +215,7 @@ if (!(core_iface_ && filesystem_iface_ && file_io_iface_ && file_ref_iface_)) { - LOG_ERROR("Got NULL interface(s): %s%s%s%s", - core_iface_ ? "" : "Core ", + LOG_ERROR("Got NULL interface(s): %s%s%s%s", core_iface_ ? "" : "Core ", filesystem_iface_ ? "" : "FileSystem ", file_ref_iface_ ? "" : "FileRef", file_io_iface_ ? "" : "FileIo "); @@ -251,8 +226,7 @@ PP_FileSystemType filesystem_type = PP_FILESYSTEMTYPE_LOCALPERSISTENT; int64_t expected_size = 0; for (StringMap_t::const_iterator iter = args.string_map.begin(); - iter != args.string_map.end(); - ++iter) { + iter != args.string_map.end(); ++iter) { if (iter->first == "type") { if (iter->second == "PERSISTENT") { filesystem_type = PP_FILESYSTEMTYPE_LOCALPERSISTENT;
diff --git a/native_client_sdk/src/libraries/nacl_io/html5fs/html5_fs.h b/native_client_sdk/src/libraries/nacl_io/html5fs/html5_fs.h index c075aa6..290f37b 100644 --- a/native_client_sdk/src/libraries/nacl_io/html5fs/html5_fs.h +++ b/native_client_sdk/src/libraries/nacl_io/html5fs/html5_fs.h
@@ -18,7 +18,9 @@ class Html5Fs : public Filesystem { public: - virtual Error OpenWithMode(const Path& path, int open_flags, mode_t mode, + virtual Error OpenWithMode(const Path& path, + int open_flags, + mode_t mode, ScopedNode* out_node); virtual Error Unlink(const Path& path); virtual Error Mkdir(const Path& path, int permissions); @@ -31,9 +33,6 @@ virtual void OnNodeCreated(Node* node); virtual void OnNodeDestroyed(Node* node); - static ino_t HashPathSegment(ino_t hash, const char *str, size_t len); - static ino_t HashPath(const Path& path); - protected: static const int REMOVE_DIR = 1; static const int REMOVE_FILE = 2;
diff --git a/native_client_sdk/src/libraries/nacl_io/html5fs/html5_fs_node.cc b/native_client_sdk/src/libraries/nacl_io/html5fs/html5_fs_node.cc index bb3a8f5ac..a5277f8c 100644 --- a/native_client_sdk/src/libraries/nacl_io/html5fs/html5_fs_node.cc +++ b/native_client_sdk/src/libraries/nacl_io/html5fs/html5_fs_node.cc
@@ -16,6 +16,7 @@ #include "nacl_io/filesystem.h" #include "nacl_io/getdents_helper.h" +#include "nacl_io/hash.h" #include "nacl_io/html5fs/html5_fs.h" #include "nacl_io/kernel_handle.h" #include "nacl_io/osdirent.h" @@ -129,8 +130,8 @@ // The INO is based on the running hash of fully qualified path, so // a childs INO must be the parent directories hash, plus '/', plus // the filename. - ino_t child_ino = Html5Fs::HashPathSegment(stat_.st_ino, file_name, - file_name_length); + ino_t child_ino = + HashPathSegment(stat_.st_ino, file_name, file_name_length); helper.AddDirent(child_ino, file_name, file_name_length); } @@ -185,11 +186,9 @@ if (IsaDir()) return EISDIR; - int32_t result = file_io_iface_->Read(fileio_resource_, - attr.offs, - static_cast<char*>(buf), - static_cast<int32_t>(count), - PP_BlockUntilComplete()); + int32_t result = file_io_iface_->Read( + fileio_resource_, attr.offs, static_cast<char*>(buf), + static_cast<int32_t>(count), PP_BlockUntilComplete()); if (result < 0) return PPERROR_TO_ERRNO(result); @@ -201,8 +200,8 @@ if (IsaDir()) return EISDIR; - int32_t result = file_io_iface_->SetLength( - fileio_resource_, size, PP_BlockUntilComplete()); + int32_t result = file_io_iface_->SetLength(fileio_resource_, size, + PP_BlockUntilComplete()); if (result != PP_OK) return PPERROR_TO_ERRNO(result); return 0; @@ -217,11 +216,9 @@ if (IsaDir()) return EISDIR; - int32_t result = file_io_iface_->Write(fileio_resource_, - attr.offs, - static_cast<const char*>(buf), - static_cast<int32_t>(count), - PP_BlockUntilComplete()); + int32_t result = file_io_iface_->Write( + fileio_resource_, attr.offs, static_cast<const char*>(buf), + static_cast<int32_t>(count), PP_BlockUntilComplete()); if (result < 0) return PPERROR_TO_ERRNO(result); @@ -254,8 +251,7 @@ Html5FsNode::Html5FsNode(Filesystem* filesystem, PP_Resource fileref_resource) : Node(filesystem), fileref_resource_(fileref_resource), - fileio_resource_(0) { -} + fileio_resource_(0) {} Error Html5FsNode::Init(int open_flags) { Error error = Node::Init(open_flags); @@ -267,10 +263,8 @@ var_iface_ = filesystem_->ppapi()->GetVarInterface(); if (!(file_io_iface_ && file_ref_iface_ && var_iface_)) { - LOG_ERROR("Got NULL interface(s): %s%s%s", - file_ref_iface_ ? "" : "FileRef", - file_io_iface_ ? "" : "FileIo ", - var_iface_ ? "" : "Var "); + LOG_ERROR("Got NULL interface(s): %s%s%s", file_ref_iface_ ? "" : "FileRef", + file_io_iface_ ? "" : "FileIo ", var_iface_ ? "" : "Var "); return EIO; } @@ -279,8 +273,8 @@ // First query the FileRef to see if it is a file or directory. PP_FileInfo file_info; - int32_t query_result = file_ref_iface_->Query( - fileref_resource_, &file_info, PP_BlockUntilComplete()); + int32_t query_result = file_ref_iface_->Query(fileref_resource_, &file_info, + PP_BlockUntilComplete()); // If this is a directory, do not get a FileIO. if (query_result == PP_OK && file_info.type == PP_FILETYPE_DIRECTORY) { return 0; @@ -293,11 +287,9 @@ return EIO; } - int32_t open_result = - file_io_iface_->Open(fileio_resource_, - fileref_resource_, - OpenFlagsToPPAPIOpenFlags(open_flags), - PP_BlockUntilComplete()); + int32_t open_result = file_io_iface_->Open( + fileio_resource_, fileref_resource_, + OpenFlagsToPPAPIOpenFlags(open_flags), PP_BlockUntilComplete()); if (open_result != PP_OK) return PPERROR_TO_ERRNO(open_result); return 0;
diff --git a/native_client_sdk/src/libraries/nacl_io/library.dsc b/native_client_sdk/src/libraries/nacl_io/library.dsc index 4e9a76fd..828bd96 100644 --- a/native_client_sdk/src/libraries/nacl_io/library.dsc +++ b/native_client_sdk/src/libraries/nacl_io/library.dsc
@@ -24,6 +24,7 @@ "fusefs/fuse_fs.cc", "fusefs/fuse_fs_factory.cc", "getdents_helper.cc", + "hash.cc", "h_errno.c", "host_resolver.cc", "html5fs/html5_fs.cc", @@ -163,6 +164,7 @@ "fusefs/fuse_fs.h", "fuse.h", "getdents_helper.h", + "hash.h", "host_resolver.h", "html5fs/html5_fs.h", "html5fs/html5_fs_node.h",
diff --git a/net/android/java/src/org/chromium/net/AndroidKeyStore.java b/net/android/java/src/org/chromium/net/AndroidKeyStore.java index b238d78..1b1e2370 100644 --- a/net/android/java/src/org/chromium/net/AndroidKeyStore.java +++ b/net/android/java/src/org/chromium/net/AndroidKeyStore.java
@@ -12,10 +12,7 @@ import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.Signature; -import java.security.interfaces.ECKey; -import java.security.interfaces.RSAKey; import java.security.interfaces.RSAPrivateKey; -import java.security.spec.ECParameterSpec; /** * Specifies all the dependencies from the native OpenSSL engine on an Android KeyStore. @@ -25,43 +22,6 @@ private static final String TAG = "AndroidKeyStore"; /** - * Returns the public modulus of a given RSA private key as a byte - * buffer. - * This can be used by native code to convert the modulus into - * an OpenSSL BIGNUM object. Required to craft a custom native RSA - * object where RSA_size() works as expected. - * - * @param privateKey A PrivateKey instance, must implement RSAKey. - * @return A byte buffer corresponding to the modulus. This is - * big-endian representation of a BigInteger. - */ - @CalledByNative - private static byte[] getRSAKeyModulus(PrivateKey privateKey) { - if (privateKey instanceof RSAKey) { - return ((RSAKey) privateKey).getModulus().toByteArray(); - } - Log.w(TAG, "Not a RSAKey instance!"); - return null; - } - - /** - * Returns the 'order' parameter of a given ECDSA private key as a - * a byte buffer. - * @param privateKey A PrivateKey instance. Must implement ECKey. - * @return A byte buffer corresponding to the 'order' parameter. - * This is a big-endian representation of a BigInteger. - */ - @CalledByNative - private static byte[] getECKeyOrder(PrivateKey privateKey) { - if (privateKey instanceof ECKey) { - ECParameterSpec params = ((ECKey) privateKey).getParams(); - return params.getOrder().toByteArray(); - } - Log.w(TAG, "Not an ECKey instance!"); - return null; - } - - /** * Sign a given message with a given PrivateKey object. This method * shall only be used to implement signing in the context of SSL * client certificate support. @@ -126,25 +86,6 @@ } } - /** - * Return the type of a given PrivateKey object. This is an integer - * that maps to one of the values defined by org.chromium.net.PrivateKeyType, - * which is itself auto-generated from net/android/private_key_type_list.h - * @param privateKey The PrivateKey handle - * @return key type, or PrivateKeyType.INVALID if unknown. - */ - @CalledByNative - private static int getPrivateKeyType(PrivateKey privateKey) { - String keyAlgorithm = privateKey.getAlgorithm(); - if ("RSA".equalsIgnoreCase(keyAlgorithm)) { - return PrivateKeyType.RSA; - } else if ("EC".equalsIgnoreCase(keyAlgorithm)) { - return PrivateKeyType.ECDSA; - } else { - return PrivateKeyType.INVALID; - } - } - private static Object getOpenSSLKeyForPrivateKey(PrivateKey privateKey) { // Sanity checks if (privateKey == null) {
diff --git a/net/android/keystore.cc b/net/android/keystore.cc index d224610..91ee41e1 100644 --- a/net/android/keystore.cc +++ b/net/android/keystore.cc
@@ -13,7 +13,6 @@ using base::android::AttachCurrentThread; using base::android::HasException; -using base::android::JavaArrayOfByteArrayToStringVector; using base::android::JavaByteArrayToByteVector; using base::android::JavaRef; using base::android::ScopedJavaLocalRef; @@ -22,33 +21,6 @@ namespace net { namespace android { -bool GetRSAKeyModulus(const JavaRef<jobject>& private_key_ref, - std::vector<uint8_t>* result) { - JNIEnv* env = AttachCurrentThread(); - - ScopedJavaLocalRef<jbyteArray> modulus_ref = - Java_AndroidKeyStore_getRSAKeyModulus(env, private_key_ref); - if (modulus_ref.is_null()) - return false; - - JavaByteArrayToByteVector(env, modulus_ref.obj(), result); - return true; -} - -bool GetECKeyOrder(const JavaRef<jobject>& private_key_ref, - std::vector<uint8_t>* result) { - JNIEnv* env = AttachCurrentThread(); - - ScopedJavaLocalRef<jbyteArray> order_ref = - Java_AndroidKeyStore_getECKeyOrder(env, private_key_ref); - - if (order_ref.is_null()) - return false; - - JavaByteArrayToByteVector(env, order_ref.obj(), result); - return true; -} - bool RawSignDigestWithPrivateKey(const JavaRef<jobject>& private_key_ref, const base::StringPiece& digest, std::vector<uint8_t>* signature) { @@ -71,12 +43,6 @@ return true; } -PrivateKeyType GetPrivateKeyType(const JavaRef<jobject>& private_key_ref) { - JNIEnv* env = AttachCurrentThread(); - int type = Java_AndroidKeyStore_getPrivateKeyType(env, private_key_ref); - return static_cast<PrivateKeyType>(type); -} - AndroidEVP_PKEY* GetOpenSSLSystemHandleForPrivateKey( const JavaRef<jobject>& private_key_ref) { JNIEnv* env = AttachCurrentThread();
diff --git a/net/android/keystore.h b/net/android/keystore.h index 7691c262..0fca8e6c 100644 --- a/net/android/keystore.h +++ b/net/android/keystore.h
@@ -27,9 +27,6 @@ // values are shared with Java through org.chromium.net.PrivateKeyType. // Example: PRIVATE_KEY_TYPE_RSA. // -// This enum is used as part of an RPC interface, so new values must be -// appended and not reused. -// // A Java counterpart will be generated for this enum. // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.net enum PrivateKeyType { @@ -39,28 +36,6 @@ PRIVATE_KEY_TYPE_INVALID = 255, }; -// Returns the modulus of a given RSAPrivateKey platform object, -// as a series of bytes, in big-endian representation. This can be -// used with BN_bin2bn() to convert to an OpenSSL BIGNUM. -// -// |private_key| is a JNI reference for the private key. -// |modulus| will receive the modulus bytes on success. -// Returns true on success, or false on failure (e.g. if the key -// is not RSA). -NET_EXPORT bool GetRSAKeyModulus( - const base::android::JavaRef<jobject>& private_key, - std::vector<uint8_t>* modulus); - -// Returns the order parameter of a given ECPrivateKey platform object, -// as a series of bytes, in big-endian representation. This can be used -// with BN_bin2bn() to convert to an OpenSSL BIGNUM. -// |private_key| is a JNI reference for the private key. -// |order| will receive the result bytes on success. -// Returns true on success, or false on failure (e.g. if the key is -// not EC). -bool GetECKeyOrder(const base::android::JavaRef<jobject>& private_key, - std::vector<uint8_t>* order); - // Compute the signature of a given message, which is actually a hash, // using a private key. For more details, please read the comments for the // rawSignDigestWithPrivateKey method in AndroidKeyStore.java. @@ -75,13 +50,6 @@ const base::StringPiece& digest, std::vector<uint8_t>* signature); -// Return the PrivateKeyType of a given private key. -// |private_key| is a JNI reference for the private key. -// Returns a PrivateKeyType, while will be CLIENT_CERT_INVALID_TYPE -// on error. -NET_EXPORT PrivateKeyType -GetPrivateKeyType(const base::android::JavaRef<jobject>& private_key); - // Returns a handle to the system AndroidEVP_PKEY object used to back a given // private_key object. This must *only* be used for RSA private keys on Android // < 4.2. Technically, this is only guaranteed to work if the system image
diff --git a/net/base/registry_controlled_domains/registry_controlled_domain.cc b/net/base/registry_controlled_domains/registry_controlled_domain.cc index 4d0d781..607d735 100644 --- a/net/base/registry_controlled_domains/registry_controlled_domain.cc +++ b/net/base/registry_controlled_domains/registry_controlled_domain.cc
@@ -148,22 +148,23 @@ (host.length() - curr_start) : 0; } -std::string GetDomainAndRegistryImpl(base::StringPiece host, - PrivateRegistryFilter private_filter) { +base::StringPiece GetDomainAndRegistryImpl( + base::StringPiece host, + PrivateRegistryFilter private_filter) { DCHECK(!host.empty()); // Find the length of the registry for this host. const size_t registry_length = GetRegistryLengthImpl(host, INCLUDE_UNKNOWN_REGISTRIES, private_filter); if ((registry_length == std::string::npos) || (registry_length == 0)) - return std::string(); // No registry. + return base::StringPiece(); // No registry. // The "2" in this next line is 1 for the dot, plus a 1-char minimum preceding // subcomponent length. DCHECK(host.length() >= 2); if (registry_length > (host.length() - 2)) { NOTREACHED() << "Host does not have at least one subcomponent before registry!"; - return std::string(); + return base::StringPiece(); } // Move past the dot preceding the registry, and search for the next previous @@ -171,28 +172,37 @@ // no dot. const size_t dot = host.rfind('.', host.length() - registry_length - 2); if (dot == std::string::npos) - return host.as_string(); - return host.substr(dot + 1).as_string(); + return host; + return host.substr(dot + 1); } -} // namespace - -std::string GetDomainAndRegistry( +// Same as GetDomainAndRegistry, but returns the domain and registry as a +// StringPiece that references the underlying string of the passed-in |gurl|. +// TODO(pkalinnikov): Eliminate this helper by exposing StringPiece as the +// interface type for all the APIs. +base::StringPiece GetDomainAndRegistryAsStringPiece( const GURL& gurl, PrivateRegistryFilter filter) { base::StringPiece host = gurl.host_piece(); if (host.empty() || gurl.HostIsIPAddress()) - return std::string(); + return base::StringPiece(); return GetDomainAndRegistryImpl(host, filter); } +} // namespace + +std::string GetDomainAndRegistry(const GURL& gurl, + PrivateRegistryFilter filter) { + return GetDomainAndRegistryAsStringPiece(gurl, filter).as_string(); +} + std::string GetDomainAndRegistry(base::StringPiece host, PrivateRegistryFilter filter) { url::CanonHostInfo host_info; const std::string canon_host(CanonicalizeHost(host, &host_info)); if (canon_host.empty() || host_info.IsIPAddress()) return std::string(); - return GetDomainAndRegistryImpl(canon_host, filter); + return GetDomainAndRegistryImpl(canon_host, filter).as_string(); } bool SameDomainOrHost( @@ -201,8 +211,10 @@ PrivateRegistryFilter filter) { // See if both URLs have a known domain + registry, and those values are the // same. - const std::string domain1(GetDomainAndRegistry(gurl1, filter)); - const std::string domain2(GetDomainAndRegistry(gurl2, filter)); + const base::StringPiece domain1 = + GetDomainAndRegistryAsStringPiece(gurl1, filter); + const base::StringPiece domain2 = + GetDomainAndRegistryAsStringPiece(gurl2, filter); if (!domain1.empty() || !domain2.empty()) return domain1 == domain2;
diff --git a/net/cert/cert_verify_proc_win.cc b/net/cert/cert_verify_proc_win.cc index a264796..e9f44fa7 100644 --- a/net/cert/cert_verify_proc_win.cc +++ b/net/cert/cert_verify_proc_win.cc
@@ -9,6 +9,7 @@ #include <vector> #include "base/memory/free_deleter.h" +#include "base/metrics/histogram_macros.h" #include "base/sha1.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -283,8 +284,44 @@ PCCERT_CONTEXT cert = element[num_elements - 1]->pCertContext; SHA256HashValue hash = X509Certificate::CalculateFingerprint256(cert); - return IsSHA256HashInSortedArray(hash, &kKnownRootCertSHA256Hashes[0][0], - sizeof(kKnownRootCertSHA256Hashes)); + bool is_builtin = + IsSHA256HashInSortedArray(hash, &kKnownRootCertSHA256Hashes[0][0], + sizeof(kKnownRootCertSHA256Hashes)); + + // Test to see if the use of a built-in set of known roots on Windows can be + // replaced with using AuthRoot's SHA-256 property. On any system other than + // a fresh RTM with no AuthRoot updates, this property should always exist for + // roots delivered via AuthRoot.stl, but should not exist on any manually or + // administratively deployed roots. + BYTE hash_prop[32] = {0}; + DWORD size = sizeof(hash_prop); + bool found_property = + CertGetCertificateContextProperty( + cert, CERT_AUTH_ROOT_SHA256_HASH_PROP_ID, &hash_prop, &size) && + size == sizeof(hash_prop); + + enum BuiltinStatus { + BUILT_IN_PROPERTY_NOT_FOUND_BUILTIN_NOT_SET = 0, + BUILT_IN_PROPERTY_NOT_FOUND_BUILTIN_SET = 1, + BUILT_IN_PROPERTY_FOUND_BUILTIN_NOT_SET = 2, + BUILT_IN_PROPERTY_FOUND_BUILTIN_SET = 3, + BUILT_IN_MAX_VALUE, + } status; + if (!found_property && !is_builtin) { + status = BUILT_IN_PROPERTY_NOT_FOUND_BUILTIN_NOT_SET; + } else if (!found_property && is_builtin) { + status = BUILT_IN_PROPERTY_NOT_FOUND_BUILTIN_SET; + } else if (found_property && !is_builtin) { + status = BUILT_IN_PROPERTY_FOUND_BUILTIN_NOT_SET; + } else if (found_property && is_builtin) { + status = BUILT_IN_PROPERTY_FOUND_BUILTIN_SET; + } else { + status = BUILT_IN_MAX_VALUE; + } + UMA_HISTOGRAM_ENUMERATION("Net.SSL_AuthRootConsistency", status, + BUILT_IN_MAX_VALUE); + + return is_builtin; } // Saves some information about the certificate chain |chain_context| in
diff --git a/net/net.gypi b/net/net.gypi index c2c903e51..3b28267 100644 --- a/net/net.gypi +++ b/net/net.gypi
@@ -1245,8 +1245,8 @@ 'ssl/ssl_platform_key_android.cc', 'ssl/ssl_platform_key_mac.cc', 'ssl/ssl_platform_key_nss.cc', - 'ssl/ssl_platform_key_task_runner.cc', - 'ssl/ssl_platform_key_task_runner.h', + 'ssl/ssl_platform_key_util.cc', + 'ssl/ssl_platform_key_util.h', 'ssl/ssl_platform_key_win.cc', 'ssl/test_ssl_private_key.cc', 'ssl/test_ssl_private_key.h', @@ -1916,6 +1916,7 @@ 'ssl/ssl_config_unittest.cc', 'ssl/ssl_connection_status_flags_unittest.cc', 'ssl/ssl_platform_key_android_unittest.cc', + 'ssl/ssl_platform_key_util_unittest.cc', 'test/embedded_test_server/embedded_test_server_unittest.cc', 'test/embedded_test_server/http_request_unittest.cc', 'test/embedded_test_server/http_response_unittest.cc',
diff --git a/net/nqe/network_quality_estimator.cc b/net/nqe/network_quality_estimator.cc index f97084a1..41947a4f 100644 --- a/net/nqe/network_quality_estimator.cc +++ b/net/nqe/network_quality_estimator.cc
@@ -389,6 +389,9 @@ base::TimeDelta::FromSeconds(10)), rtt_observations_size_at_last_ect_computation_(0), throughput_observations_size_at_last_ect_computation_(0), + http_rtt_(nqe::internal::InvalidRTT()), + transport_rtt_(nqe::internal::InvalidRTT()), + downstream_throughput_kbps_(nqe::internal::kInvalidThroughput), effective_connection_type_(EFFECTIVE_CONNECTION_TYPE_UNKNOWN), min_signal_strength_since_connection_change_(INT32_MAX), max_signal_strength_since_connection_change_(INT32_MIN), @@ -979,9 +982,8 @@ void NetworkQualityEstimator::ReportEffectiveConnectionTypeForTesting( EffectiveConnectionType effective_connection_type) { DCHECK(thread_checker_.CalledOnValidThread()); - FOR_EACH_OBSERVER( - EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, - OnEffectiveConnectionTypeChanged(effective_connection_type)); + for (auto& observer : effective_connection_type_observer_list_) + observer.OnEffectiveConnectionTypeChanged(effective_connection_type); } bool NetworkQualityEstimator::RequestProvidesRTTObservation( @@ -1032,6 +1034,9 @@ min_signal_strength_since_connection_change_ = INT32_MAX; max_signal_strength_since_connection_change_ = INT32_MIN; estimated_quality_at_last_main_frame_ = nqe::internal::NetworkQuality(); + http_rtt_ = nqe::internal::InvalidRTT(); + transport_rtt_ = nqe::internal::InvalidRTT(); + downstream_throughput_kbps_ = nqe::internal::kInvalidThroughput; effective_connection_type_ = EFFECTIVE_CONNECTION_TYPE_UNKNOWN; effective_connection_type_at_last_main_frame_ = EFFECTIVE_CONNECTION_TYPE_UNKNOWN; @@ -1212,7 +1217,10 @@ last_effective_connection_type_computation_ = now; effective_connection_type_ = - GetRecentEffectiveConnectionType(base::TimeTicks()); + GetRecentEffectiveConnectionTypeAndNetworkQuality( + base::TimeTicks(), &http_rtt_, &transport_rtt_, + &downstream_throughput_kbps_); + NotifyObserversOfRTTOrThroughputComputed(); if (past_type != effective_connection_type_) NotifyObserversOfEffectiveConnectionTypeChanged(); @@ -1233,6 +1241,22 @@ const base::TimeTicks& start_time) const { DCHECK(thread_checker_.CalledOnValidThread()); + base::TimeDelta http_rtt; + base::TimeDelta transport_rtt; + int32_t downstream_throughput_kbps; + + return GetRecentEffectiveConnectionTypeAndNetworkQuality( + start_time, &http_rtt, &transport_rtt, &downstream_throughput_kbps); +} + +EffectiveConnectionType +NetworkQualityEstimator::GetRecentEffectiveConnectionTypeAndNetworkQuality( + const base::TimeTicks& start_time, + base::TimeDelta* http_rtt, + base::TimeDelta* transport_rtt, + int32_t* downstream_throughput_kbps) const { + DCHECK(thread_checker_.CalledOnValidThread()); + if (effective_connection_type_algorithm_ == EffectiveConnectionTypeAlgorithm::HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT) { return GetRecentEffectiveConnectionTypeUsingMetrics( @@ -1241,7 +1265,8 @@ NetworkQualityEstimator::MetricUsage:: DO_NOT_USE /* transport_rtt_metric */, NetworkQualityEstimator::MetricUsage:: - MUST_BE_USED /* downstream_throughput_kbps_metric */); + MUST_BE_USED /* downstream_throughput_kbps_metric */, + http_rtt, transport_rtt, downstream_throughput_kbps); } if (effective_connection_type_algorithm_ == EffectiveConnectionTypeAlgorithm:: @@ -1252,7 +1277,8 @@ NetworkQualityEstimator::MetricUsage:: USE_IF_AVAILABLE /* transport_rtt_metric */, NetworkQualityEstimator::MetricUsage:: - USE_IF_AVAILABLE /* downstream_throughput_kbps_metric */); + USE_IF_AVAILABLE /* downstream_throughput_kbps_metric */, + http_rtt, transport_rtt, downstream_throughput_kbps); } // Add additional algorithms here. NOTREACHED(); @@ -1281,10 +1307,16 @@ const base::TimeTicks& start_time, NetworkQualityEstimator::MetricUsage http_rtt_metric, NetworkQualityEstimator::MetricUsage transport_rtt_metric, - NetworkQualityEstimator::MetricUsage downstream_throughput_kbps_metric) - const { + NetworkQualityEstimator::MetricUsage downstream_throughput_kbps_metric, + base::TimeDelta* http_rtt, + base::TimeDelta* transport_rtt, + int32_t* downstream_throughput_kbps) const { DCHECK(thread_checker_.CalledOnValidThread()); + *http_rtt = nqe::internal::InvalidRTT(); + *transport_rtt = nqe::internal::InvalidRTT(); + *downstream_throughput_kbps = nqe::internal::kInvalidThroughput; + if (forced_effective_connection_type_set_) return forced_effective_connection_type_; @@ -1293,46 +1325,35 @@ if (current_network_id_.type == NetworkChangeNotifier::CONNECTION_NONE) return EFFECTIVE_CONNECTION_TYPE_OFFLINE; - base::TimeDelta http_rtt = nqe::internal::InvalidRTT(); - if (http_rtt_metric != NetworkQualityEstimator::MetricUsage::DO_NOT_USE && - !GetRecentHttpRTT(start_time, &http_rtt)) { - http_rtt = nqe::internal::InvalidRTT(); - } + if (!GetRecentHttpRTT(start_time, http_rtt)) + *http_rtt = nqe::internal::InvalidRTT(); - base::TimeDelta transport_rtt = nqe::internal::InvalidRTT(); - if (transport_rtt_metric != - NetworkQualityEstimator::MetricUsage::DO_NOT_USE && - !GetRecentTransportRTT(start_time, &transport_rtt)) { - transport_rtt = nqe::internal::InvalidRTT(); - } + if (!GetRecentTransportRTT(start_time, transport_rtt)) + *transport_rtt = nqe::internal::InvalidRTT(); - int32_t kbps = nqe::internal::kInvalidThroughput; - if (downstream_throughput_kbps_metric != - NetworkQualityEstimator::MetricUsage::DO_NOT_USE && - !GetRecentDownlinkThroughputKbps(start_time, &kbps)) { - kbps = nqe::internal::kInvalidThroughput; - } + if (!GetRecentDownlinkThroughputKbps(start_time, downstream_throughput_kbps)) + *downstream_throughput_kbps = nqe::internal::kInvalidThroughput; - if (http_rtt == nqe::internal::InvalidRTT() && + if (*http_rtt == nqe::internal::InvalidRTT() && http_rtt_metric == NetworkQualityEstimator::MetricUsage::MUST_BE_USED) { return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; } - if (transport_rtt == nqe::internal::InvalidRTT() && + if (*transport_rtt == nqe::internal::InvalidRTT() && transport_rtt_metric == NetworkQualityEstimator::MetricUsage::MUST_BE_USED) { return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; } - if (kbps == nqe::internal::kInvalidThroughput && + if (*downstream_throughput_kbps == nqe::internal::kInvalidThroughput && downstream_throughput_kbps_metric == NetworkQualityEstimator::MetricUsage::MUST_BE_USED) { return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; } - if (http_rtt == nqe::internal::InvalidRTT() && - transport_rtt == nqe::internal::InvalidRTT() && - kbps == nqe::internal::kInvalidThroughput) { + if (*http_rtt == nqe::internal::InvalidRTT() && + *transport_rtt == nqe::internal::InvalidRTT() && + *downstream_throughput_kbps == nqe::internal::kInvalidThroughput) { // None of the metrics are available. return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; } @@ -1346,21 +1367,27 @@ continue; const bool estimated_http_rtt_is_higher_than_threshold = - http_rtt != nqe::internal::InvalidRTT() && + http_rtt_metric != NetworkQualityEstimator::MetricUsage::DO_NOT_USE && + *http_rtt != nqe::internal::InvalidRTT() && connection_thresholds_[i].http_rtt() != nqe::internal::InvalidRTT() && - http_rtt >= connection_thresholds_[i].http_rtt(); + *http_rtt >= connection_thresholds_[i].http_rtt(); const bool estimated_transport_rtt_is_higher_than_threshold = - transport_rtt != nqe::internal::InvalidRTT() && + transport_rtt_metric != + NetworkQualityEstimator::MetricUsage::DO_NOT_USE && + *transport_rtt != nqe::internal::InvalidRTT() && connection_thresholds_[i].transport_rtt() != nqe::internal::InvalidRTT() && - transport_rtt >= connection_thresholds_[i].transport_rtt(); + *transport_rtt >= connection_thresholds_[i].transport_rtt(); const bool estimated_throughput_is_lower_than_threshold = - kbps != nqe::internal::kInvalidThroughput && + downstream_throughput_kbps_metric != + NetworkQualityEstimator::MetricUsage::DO_NOT_USE && + *downstream_throughput_kbps != nqe::internal::kInvalidThroughput && connection_thresholds_[i].downstream_throughput_kbps() != nqe::internal::kInvalidThroughput && - kbps <= connection_thresholds_[i].downstream_throughput_kbps(); + *downstream_throughput_kbps <= + connection_thresholds_[i].downstream_throughput_kbps(); if (estimated_http_rtt_is_higher_than_threshold || estimated_transport_rtt_is_higher_than_threshold || @@ -1385,6 +1412,18 @@ effective_connection_type_observer_list_.RemoveObserver(observer); } +void NetworkQualityEstimator::AddRTTAndThroughputEstimatesObserver( + RTTAndThroughputEstimatesObserver* observer) { + DCHECK(thread_checker_.CalledOnValidThread()); + rtt_and_throughput_estimates_observer_list_.AddObserver(observer); +} + +void NetworkQualityEstimator::RemoveRTTAndThroughputEstimatesObserver( + RTTAndThroughputEstimatesObserver* observer) { + DCHECK(thread_checker_.CalledOnValidThread()); + rtt_and_throughput_estimates_observer_list_.RemoveObserver(observer); +} + bool NetworkQualityEstimator::GetHttpRTT(base::TimeDelta* rtt) const { DCHECK(thread_checker_.CalledOnValidThread()); return GetRecentHttpRTT(base::TimeTicks(), rtt); @@ -1537,6 +1576,10 @@ if (effective_connection_type_ == EFFECTIVE_CONNECTION_TYPE_UNKNOWN) { // Read the effective connection type from the cached estimate. last_effective_connection_type_computation_ = now; + http_rtt_ = cached_network_quality.network_quality().http_rtt(); + transport_rtt_ = cached_network_quality.network_quality().transport_rtt(); + downstream_throughput_kbps_ = + cached_network_quality.network_quality().downstream_throughput_kbps(); effective_connection_type_ = cached_network_quality.effective_connection_type(); @@ -1631,10 +1674,10 @@ // Maybe recompute the effective connection type since a new RTT observation // is available. MaybeComputeEffectiveConnectionType(); - FOR_EACH_OBSERVER( - RTTObserver, rtt_observer_list_, - OnRTTObservation(observation.value.InMilliseconds(), - observation.timestamp, observation.source)); + for (auto& observer : rtt_observer_list_) { + observer.OnRTTObservation(observation.value.InMilliseconds(), + observation.timestamp, observation.source); + } } void NetworkQualityEstimator::NotifyObserversOfThroughput( @@ -1645,10 +1688,10 @@ // Maybe recompute the effective connection type since a new throughput // observation is available. MaybeComputeEffectiveConnectionType(); - FOR_EACH_OBSERVER( - ThroughputObserver, throughput_observer_list_, - OnThroughputObservation(observation.value, observation.timestamp, - observation.source)); + for (auto& observer : throughput_observer_list_) { + observer.OnThroughputObservation(observation.value, observation.timestamp, + observation.source); + } } void NetworkQualityEstimator::OnNewThroughputObservationAvailable( @@ -1707,9 +1750,8 @@ DCHECK_NE(EFFECTIVE_CONNECTION_TYPE_LAST, effective_connection_type_); // TODO(tbansal): Add hysteresis in the notification. - FOR_EACH_OBSERVER( - EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, - OnEffectiveConnectionTypeChanged(effective_connection_type_)); + for (auto& observer : effective_connection_type_observer_list_) + observer.OnEffectiveConnectionTypeChanged(effective_connection_type_); // Add the estimates of the current network to the cache store. if (effective_connection_type_ != EFFECTIVE_CONNECTION_TYPE_UNKNOWN) { @@ -1721,6 +1763,16 @@ } } +void NetworkQualityEstimator::NotifyObserversOfRTTOrThroughputComputed() const { + DCHECK(thread_checker_.CalledOnValidThread()); + + // TODO(tbansal): Add hysteresis in the notification. + for (auto& observer : rtt_and_throughput_estimates_observer_list_) { + observer.OnRTTOrThroughputEstimatesComputed(http_rtt_, transport_rtt_, + downstream_throughput_kbps_); + } +} + void NetworkQualityEstimator::AddNetworkQualitiesCacheObserver( nqe::internal::NetworkQualityStore::NetworkQualitiesCacheObserver* observer) {
diff --git a/net/nqe/network_quality_estimator.h b/net/nqe/network_quality_estimator.h index 46b6a8f5..7c3525e 100644 --- a/net/nqe/network_quality_estimator.h +++ b/net/nqe/network_quality_estimator.h
@@ -84,6 +84,36 @@ DISALLOW_COPY_AND_ASSIGN(EffectiveConnectionTypeObserver); }; + // Observes changes in the network quality. + class NET_EXPORT RTTAndThroughputEstimatesObserver { + public: + // Notifies the observer when estimated HTTP RTT, estimated transport RTT or + // estimated downstream throughput is computed. NetworkQualityEstimator + // computes the RTT and throughput estimates at regular intervals. + // Additionally, when there is a change in the connection type of the + // device, then the estimates are immediately computed. The observer must + // register and unregister itself on the IO thread. All the observers would + // be notified on the IO thread. + // + // |http_rtt|, |transport_rtt| and |downstream_throughput_kbps| are the + // computed estimates of the HTTP RTT, transport RTT and downstream + // throughput (in kilobits per second), respectively. If an estimate of the + // HTTP or transport RTT is unavailable, it will be set to + // nqe::internal::InvalidRTT(). If the throughput estimate is unavailable, + // it will be set to nqe::internal::kInvalidThroughput. + virtual void OnRTTOrThroughputEstimatesComputed( + base::TimeDelta http_rtt, + base::TimeDelta transport_rtt, + int32_t downstream_throughput_kbps) = 0; + + protected: + RTTAndThroughputEstimatesObserver() {} + virtual ~RTTAndThroughputEstimatesObserver() {} + + private: + DISALLOW_COPY_AND_ASSIGN(RTTAndThroughputEstimatesObserver); + }; + // Observes measurements of round trip time. class NET_EXPORT_PRIVATE RTTObserver { public: @@ -185,6 +215,16 @@ void RemoveEffectiveConnectionTypeObserver( EffectiveConnectionTypeObserver* observer); + // Adds |observer| to the list of RTT and throughput estimate observers. Must + // be called on the IO thread. + void AddRTTAndThroughputEstimatesObserver( + RTTAndThroughputEstimatesObserver* observer); + + // Removes |observer| from the list of RTT and throughput estimate observers. + // Must be called on the IO thread. + void RemoveRTTAndThroughputEstimatesObserver( + RTTAndThroughputEstimatesObserver* observer); + // Notifies NetworkQualityEstimator that the response header of |request| has // been received. void NotifyHeadersReceived(const URLRequest& request); @@ -308,6 +348,19 @@ // Returns a random double in the range [0.0, 1.0). Virtualized for testing. virtual double RandDouble() const; + // Returns the effective type of the current connection based on only the + // observations received after |start_time|. |http_rtt|, |transport_rtt| and + // |downstream_throughput_kbps| must be non-null. |http_rtt|, |transport_rtt| + // and |downstream_throughput_kbps| are set to the expected HTTP RTT, + // transport RTT and downstream throughput (in kilobits per second) based on + // observations taken since |start_time|. Virtualized for testing. + virtual EffectiveConnectionType + GetRecentEffectiveConnectionTypeAndNetworkQuality( + const base::TimeTicks& start_time, + base::TimeDelta* http_rtt, + base::TimeDelta* transport_rtt, + int32_t* downstream_throughput_kbps) const; + private: FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, AdaptiveRecomputationEffectiveConnectionType); @@ -450,9 +503,12 @@ // specified duration ago, or if there has been a connection change recently. void MaybeComputeEffectiveConnectionType(); - // Notify observers of a change in effective connection type. + // Notifies observers of a change in effective connection type. void NotifyObserversOfEffectiveConnectionTypeChanged(); + // Notifies the observers of RTT or throughput estimates computation. + void NotifyObserversOfRTTOrThroughputComputed() const; + // Records NQE accuracy metrics. |measuring_duration| should belong to the // vector returned by AccuracyRecordingIntervals(). // RecordAccuracyAfterMainFrame should be called |measuring_duration| after a @@ -468,12 +524,19 @@ // samples observed after |start_time|. May use HTTP RTT, transport RTT and // downstream throughput to compute the effective connection type based on // |http_rtt_metric|, |transport_rtt_metric| and - // |downstream_throughput_kbps_metric|, respectively. + // |downstream_throughput_kbps_metric|, respectively. |http_rtt|, + // |transport_rtt| and |downstream_throughput_kbps| must be non-null. + // |http_rtt|, |transport_rtt| and |downstream_throughput_kbps| are + // set to the expected HTTP RTT, transport RTT and downstream throughput (in + // kilobits per second) based on observations taken since |start_time|. EffectiveConnectionType GetRecentEffectiveConnectionTypeUsingMetrics( const base::TimeTicks& start_time, MetricUsage http_rtt_metric, MetricUsage transport_rtt_metric, - MetricUsage downstream_throughput_kbps_metric) const; + MetricUsage downstream_throughput_kbps_metric, + base::TimeDelta* http_rtt, + base::TimeDelta* transport_rtt, + int32_t* downstream_throughput_kbps) const; // Values of external estimate provider status. This enum must remain // synchronized with the enum of the same name in @@ -594,6 +657,10 @@ base::ObserverList<EffectiveConnectionTypeObserver> effective_connection_type_observer_list_; + // Observer list for RTT or throughput estimates. + base::ObserverList<RTTAndThroughputEstimatesObserver> + rtt_and_throughput_estimates_observer_list_; + // Observer lists for round trip times and throughput measurements. base::ObserverList<RTTObserver> rtt_observer_list_; base::ObserverList<ThroughputObserver> throughput_observer_list_; @@ -618,6 +685,12 @@ size_t rtt_observations_size_at_last_ect_computation_; size_t throughput_observations_size_at_last_ect_computation_; + // Current estimates of the HTTP RTT, transport RTT and downstream throughput + // (in kilobits per second). + base::TimeDelta http_rtt_; + base::TimeDelta transport_rtt_; + int32_t downstream_throughput_kbps_; + // Current effective connection type. It is updated on connection change // events. It is also updated every time there is network traffic (provided // the last computation was more than
diff --git a/net/nqe/network_quality_estimator_test_util.cc b/net/nqe/network_quality_estimator_test_util.cc index 80e7889..db9e283 100644 --- a/net/nqe/network_quality_estimator_test_util.cc +++ b/net/nqe/network_quality_estimator_test_util.cc
@@ -109,6 +109,23 @@ return NetworkQualityEstimator::GetRecentEffectiveConnectionType(start_time); } +EffectiveConnectionType +TestNetworkQualityEstimator::GetRecentEffectiveConnectionTypeAndNetworkQuality( + const base::TimeTicks& start_time, + base::TimeDelta* http_rtt, + base::TimeDelta* transport_rtt, + int32_t* downstream_throughput_kbps) const { + if (recent_effective_connection_type_set_) { + *http_rtt = recent_http_rtt_; + *transport_rtt = recent_transport_rtt_; + *downstream_throughput_kbps = recent_downlink_throughput_kbps_; + return recent_effective_connection_type_; + } + return NetworkQualityEstimator:: + GetRecentEffectiveConnectionTypeAndNetworkQuality( + start_time, http_rtt, transport_rtt, downstream_throughput_kbps); +} + bool TestNetworkQualityEstimator::GetHttpRTT(base::TimeDelta* rtt) const { if (http_rtt_set_) { *rtt = http_rtt_;
diff --git a/net/nqe/network_quality_estimator_test_util.h b/net/nqe/network_quality_estimator_test_util.h index 5bad67d..5e6399d 100644 --- a/net/nqe/network_quality_estimator_test_util.h +++ b/net/nqe/network_quality_estimator_test_util.h
@@ -84,6 +84,18 @@ EffectiveConnectionType GetRecentEffectiveConnectionType( const base::TimeTicks& start_time) const override; + // Returns the effective connection type that was set using + // |set_effective_connection_type|. If the connection type has not been set, + // then the base implementation is called. |http_rtt|, |transport_rtt| and + // |downstream_throughput_kbps| are set to the values that were previously + // set by calling set_recent_http_rtt(), set_recent_transport_rtt() + // and set_recent_transport_rtt() methods, respectively. + EffectiveConnectionType GetRecentEffectiveConnectionTypeAndNetworkQuality( + const base::TimeTicks& start_time, + base::TimeDelta* http_rtt, + base::TimeDelta* transport_rtt, + int32_t* downstream_throughput_kbps) const override; + void set_http_rtt(const base::TimeDelta& http_rtt) { http_rtt_set_ = true; http_rtt_ = http_rtt;
diff --git a/net/nqe/network_quality_estimator_unittest.cc b/net/nqe/network_quality_estimator_unittest.cc index 442a42b3..ea75ec2c 100644 --- a/net/nqe/network_quality_estimator_unittest.cc +++ b/net/nqe/network_quality_estimator_unittest.cc
@@ -60,6 +60,41 @@ std::vector<EffectiveConnectionType> effective_connection_types_; }; +class TestRTTAndThroughputEstimatesObserver + : public NetworkQualityEstimator::RTTAndThroughputEstimatesObserver { + public: + TestRTTAndThroughputEstimatesObserver() + : http_rtt_(nqe::internal::InvalidRTT()), + transport_rtt_(nqe::internal::InvalidRTT()), + downstream_throughput_kbps_(nqe::internal::kInvalidThroughput), + notifications_received_(0) {} + + // RTTAndThroughputEstimatesObserver implementation: + void OnRTTOrThroughputEstimatesComputed( + base::TimeDelta http_rtt, + base::TimeDelta transport_rtt, + int32_t downstream_throughput_kbps) override { + http_rtt_ = http_rtt; + transport_rtt_ = transport_rtt; + downstream_throughput_kbps_ = downstream_throughput_kbps; + notifications_received_++; + } + + int notifications_received() const { return notifications_received_; } + + base::TimeDelta http_rtt() const { return http_rtt_; } + base::TimeDelta transport_rtt() const { return transport_rtt_; } + int32_t downstream_throughput_kbps() const { + return downstream_throughput_kbps_; + } + + private: + base::TimeDelta http_rtt_; + base::TimeDelta transport_rtt_; + int32_t downstream_throughput_kbps_; + int notifications_received_; +}; + class TestRTTObserver : public NetworkQualityEstimator::RTTObserver { public: struct Observation { @@ -1337,6 +1372,75 @@ EXPECT_EQ(2U, observer.effective_connection_types().size()); } +// Tests that the network quality is computed at the specified interval, and +// that the network quality observers are notified of any change. +TEST(NetworkQualityEstimatorTest, TestRTTAndThroughputEstimatesObserver) { + base::HistogramTester histogram_tester; + std::unique_ptr<base::SimpleTestTickClock> tick_clock( + new base::SimpleTestTickClock()); + base::SimpleTestTickClock* tick_clock_ptr = tick_clock.get(); + + TestRTTAndThroughputEstimatesObserver observer; + std::map<std::string, std::string> variation_params; + TestNetworkQualityEstimator estimator(variation_params); + estimator.AddRTTAndThroughputEstimatesObserver(&observer); + estimator.SetTickClockForTesting(std::move(tick_clock)); + + TestDelegate test_delegate; + TestURLRequestContext context(true); + context.set_network_quality_estimator(&estimator); + context.Init(); + + EXPECT_EQ(nqe::internal::InvalidRTT(), observer.http_rtt()); + EXPECT_EQ(nqe::internal::InvalidRTT(), observer.transport_rtt()); + EXPECT_EQ(nqe::internal::kInvalidThroughput, + observer.downstream_throughput_kbps()); + int notifications_received = observer.notifications_received(); + EXPECT_EQ(0, notifications_received); + + base::TimeDelta http_rtt(base::TimeDelta::FromMilliseconds(100)); + base::TimeDelta transport_rtt(base::TimeDelta::FromMilliseconds(200)); + int32_t downstream_throughput_kbps(300); + estimator.set_recent_effective_connection_type(EFFECTIVE_CONNECTION_TYPE_2G); + estimator.set_recent_http_rtt(http_rtt); + estimator.set_recent_transport_rtt(transport_rtt); + estimator.set_recent_downlink_throughput_kbps(downstream_throughput_kbps); + tick_clock_ptr->Advance(base::TimeDelta::FromMinutes(60)); + + std::unique_ptr<URLRequest> request(context.CreateRequest( + estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); + request->Start(); + base::RunLoop().Run(); + EXPECT_EQ(http_rtt, observer.http_rtt()); + EXPECT_EQ(transport_rtt, observer.transport_rtt()); + EXPECT_EQ(downstream_throughput_kbps, observer.downstream_throughput_kbps()); + EXPECT_LE(1, observer.notifications_received() - notifications_received); + notifications_received = observer.notifications_received(); + + // The next request should not trigger recomputation of RTT or throughput + // since there has been no change in the clock. + std::unique_ptr<URLRequest> request2(context.CreateRequest( + estimator.GetEchoURL(), DEFAULT_PRIORITY, &test_delegate)); + request2->Start(); + base::RunLoop().Run(); + EXPECT_LE(1, observer.notifications_received() - notifications_received); + notifications_received = observer.notifications_received(); + + // A change in the connection type should send out notification to the + // observers. + estimator.set_effective_connection_type(EFFECTIVE_CONNECTION_TYPE_3G); + estimator.SimulateNetworkChange(NetworkChangeNotifier::CONNECTION_WIFI, + "test"); + EXPECT_LE(1, observer.notifications_received() - notifications_received); + notifications_received = observer.notifications_received(); + + // A change in effective connection type does not trigger notification to the + // observers, since it is not accompanied by any new observation or a network + // change event. + estimator.set_recent_effective_connection_type(EFFECTIVE_CONNECTION_TYPE_3G); + EXPECT_EQ(0, observer.notifications_received() - notifications_received); +} + // Tests that the effective connection type is computed on every RTT // observation if the last computed effective connection type was unknown. TEST(NetworkQualityEstimatorTest, UnknownEffectiveConnectionType) {
diff --git a/net/quic/chromium/quic_chromium_client_session.cc b/net/quic/chromium/quic_chromium_client_session.cc index 1fd83189..85c47f8 100644 --- a/net/quic/chromium/quic_chromium_client_session.cc +++ b/net/quic/chromium/quic_chromium_client_session.cc
@@ -539,9 +539,9 @@ ssl_info->cert_status = cert_verify_result_->cert_status; ssl_info->cert = cert_verify_result_->verified_cert; - // TODO(wtc): Define QUIC "cipher suites". - // Report the TLS cipher suite that most closely resembles the crypto - // parameters of the QUIC connection. + // TODO(davidben): Switch these to the TLS 1.3 AEAD-only ciphers. That will + // place them in the cache in the default configuration, so do this when we + // are comfortable supporting those values long-term. QuicTag aead = crypto_stream_->crypto_negotiated_params().aead; uint16_t cipher_suite; int security_bits;
diff --git a/net/quic/core/quic_flags_list.h b/net/quic/core/quic_flags_list.h index de0df47..15e1b7a 100644 --- a/net/quic/core/quic_flags_list.h +++ b/net/quic/core/quic_flags_list.h
@@ -158,3 +158,7 @@ // If true, will send QUIC_PUSH_STREAM_TIMED_OUT when push stream is unclaimed // and times out. QUIC_FLAG(bool, FLAGS_quic_send_push_stream_timed_out_error, true) + +// If true, enable bugfix for FHOL experiment (fin-only +// WritevStreamData). +QUIC_FLAG(bool, FLAGS_quic_bugfix_fhol_writev_fin_only_v2, true)
diff --git a/net/quic/core/quic_headers_stream.cc b/net/quic/core/quic_headers_stream.cc index b6e8a5e..a31a326 100644 --- a/net/quic/core/quic_headers_stream.cc +++ b/net/quic/core/quic_headers_stream.cc
@@ -387,6 +387,25 @@ return frame.size(); } +void QuicHeadersStream::WriteDataFrame( + QuicStreamId id, + StringPiece data, + bool fin, + QuicAckListenerInterface* ack_notifier_delegate) { + SpdyDataIR spdy_data(id, data); + spdy_data.set_fin(fin); + SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data)); + scoped_refptr<ForceHolAckListener> ack_listener; + if (ack_notifier_delegate != nullptr) { + ack_listener = new ForceHolAckListener(ack_notifier_delegate, + frame.size() - data.length()); + } + // Use buffered writes so that coherence of framing is preserved + // between streams. + WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, + ack_listener.get()); +} + QuicConsumedData QuicHeadersStream::WritevStreamData( QuicStreamId id, QuicIOVector iov, @@ -399,48 +418,92 @@ QuicConsumedData result(0, false); size_t total_length = iov.total_length; - // Encapsulate the data into HTTP/2 DATA frames. The outer loop - // handles each element of the source iov, the inner loop handles - // the possibility of fragmenting eacho of those into multiple DATA - // frames, as the DATA frames have a max size of 16KB. - for (int i = 0; i < iov.iov_count; i++) { - size_t offset = 0; - const struct iovec* src_iov = &iov.iov[i]; - do { - size_t len = - std::min(std::min(src_iov->iov_len - offset, max_len), total_length); - char* data = static_cast<char*>(src_iov->iov_base) + offset; - SpdyDataIR spdy_data(id, StringPiece(data, len)); - offset += len; - // fin handling, set it only it only very last generated HTTP/2 - // DATA frame. - bool last_iov = i == iov.iov_count - 1; - bool last_fragment_within_iov = offset >= src_iov->iov_len; - bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false; - spdy_data.set_fin(frame_fin); - if (frame_fin) { - result.fin_consumed = true; - } - SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data)); - DVLOG(1) << "Encapsulating in DATA frame for stream " << id << " len " - << len << " fin " << spdy_data.fin() << " remaining " - << src_iov->iov_len - offset; + if (!FLAGS_quic_bugfix_fhol_writev_fin_only_v2) { + // Encapsulate the data into HTTP/2 DATA frames. The outer loop + // handles each element of the source iov, the inner loop handles + // the possibility of fragmenting eacho of those into multiple DATA + // frames, as the DATA frames have a max size of 16KB. + for (int i = 0; i < iov.iov_count; i++) { + size_t offset = 0; + const struct iovec* src_iov = &iov.iov[i]; + do { + size_t len = std::min(std::min(src_iov->iov_len - offset, max_len), + total_length); + char* data = static_cast<char*>(src_iov->iov_base) + offset; + SpdyDataIR spdy_data(id, StringPiece(data, len)); + offset += len; + // fin handling, only set it for the final HTTP/2 DATA frame. + bool last_iov = i == iov.iov_count - 1; + bool last_fragment_within_iov = offset >= src_iov->iov_len; + bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false; + spdy_data.set_fin(frame_fin); + if (frame_fin) { + result.fin_consumed = true; + } + SpdySerializedFrame frame(spdy_framer_.SerializeFrame(spdy_data)); + DVLOG(1) << "Encapsulating in DATA frame for stream " << id << " len " + << len << " fin " << spdy_data.fin() << " remaining " + << src_iov->iov_len - offset; - scoped_refptr<ForceHolAckListener> ack_listener; - if (ack_notifier_delegate != nullptr) { - ack_listener = - new ForceHolAckListener(ack_notifier_delegate, frame.size() - len); - } + scoped_refptr<ForceHolAckListener> ack_listener; + if (ack_notifier_delegate != nullptr) { + ack_listener = new ForceHolAckListener(ack_notifier_delegate, + frame.size() - len); + } - WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, - ack_listener.get()); - result.bytes_consumed += len; - total_length -= len; - if (total_length <= 0) { - return result; - } - } while (offset < src_iov->iov_len); + WriteOrBufferData(StringPiece(frame.data(), frame.size()), false, + ack_listener.get()); + result.bytes_consumed += len; + total_length -= len; + if (total_length <= 0) { + return result; + } + } while (offset < src_iov->iov_len); + } + } else { + if (total_length == 0 && fin) { + WriteDataFrame(id, StringPiece(), true, ack_notifier_delegate); + result.fin_consumed = true; + return result; + } + + // Encapsulate the data into HTTP/2 DATA frames. The outer loop + // handles each element of the source iov, the inner loop handles + // the possibility of fragmenting each of those into multiple DATA + // frames, as the DATA frames have a max size of 16KB. + for (int i = 0; i < iov.iov_count; i++) { + size_t src_iov_offset = 0; + const struct iovec* src_iov = &iov.iov[i]; + do { + if (queued_data_bytes() > 0) { + // Limit the amount of buffering to the minimum needed to + // preserve framing. + return result; + } + size_t len = std::min( + std::min(src_iov->iov_len - src_iov_offset, max_len), total_length); + char* data = static_cast<char*>(src_iov->iov_base) + src_iov_offset; + src_iov_offset += len; + offset += len; + // fin handling, only set it for the final HTTP/2 DATA frame. + bool last_iov = i == iov.iov_count - 1; + bool last_fragment_within_iov = src_iov_offset >= src_iov->iov_len; + bool frame_fin = (last_iov && last_fragment_within_iov) ? fin : false; + WriteDataFrame(id, StringPiece(data, len), frame_fin, + ack_notifier_delegate); + result.bytes_consumed += len; + if (frame_fin) { + result.fin_consumed = true; + } + DCHECK_GE(total_length, len); + total_length -= len; + if (total_length <= 0) { + return result; + } + } while (src_iov_offset < src_iov->iov_len); + } } + return result; }
diff --git a/net/quic/core/quic_headers_stream.h b/net/quic/core/quic_headers_stream.h index 603dd45..209def4 100644 --- a/net/quic/core/quic_headers_stream.h +++ b/net/quic/core/quic_headers_stream.h
@@ -136,10 +136,15 @@ void OnCompressedFrameSize(size_t frame_len); // For force HOL blocking, where stream frames from all streams are - // plumbed through headers stream as HTTP/2 data frames. Return false - // if force_hol_blocking_ is false; + // plumbed through headers stream as HTTP/2 data frames. + // The following two return false if force_hol_blocking_ is false. bool OnDataFrameHeader(QuicStreamId stream_id, size_t length, bool fin); bool OnStreamFrameData(QuicStreamId stream_id, const char* data, size_t len); + // Helper for |WritevStreamData()|. + void WriteDataFrame(QuicStreamId stream_id, + base::StringPiece data, + bool fin, + QuicAckListenerInterface* ack_notifier_delegate); // Returns true if the session is still connected. bool IsConnected();
diff --git a/net/quic/core/quic_headers_stream_test.cc b/net/quic/core/quic_headers_stream_test.cc index c1ca9fbb..cdb0ad59 100644 --- a/net/quic/core/quic_headers_stream_test.cc +++ b/net/quic/core/quic_headers_stream_test.cc
@@ -260,6 +260,13 @@ return QuicConsumedData(consumed, false); } + QuicConsumedData SaveIovShort(const QuicIOVector& data) { + const iovec* iov = data.iov; + int consumed = 1; + saved_data_.append(static_cast<char*>(iov[0].iov_base), consumed); + return QuicConsumedData(consumed, false); + } + QuicConsumedData SaveIovAndNotifyAckListener( const QuicIOVector& data, QuicAckListenerInterface* ack_listener) { @@ -992,6 +999,68 @@ } } +TEST_P(QuicHeadersStreamTest, WritevStreamDataFinOnly) { + FLAGS_quic_bugfix_fhol_writev_fin_only_v2 = true; + struct iovec iov; + string data; + + EXPECT_CALL(session_, + WritevData(headers_stream_, kHeadersStreamId, _, _, false, _)) + .WillOnce(WithArgs<2, 5>( + Invoke(this, &QuicHeadersStreamTest::SaveIovAndNotifyAckListener))); + + QuicConsumedData consumed_data = headers_stream_->WritevStreamData( + kClientDataStreamId1, MakeIOVector(data, &iov), 0, true, nullptr); + + EXPECT_EQ(consumed_data.bytes_consumed, 0u); + EXPECT_EQ(consumed_data.fin_consumed, true); +} + +TEST_P(QuicHeadersStreamTest, WritevStreamDataSendBlocked) { + FLAGS_quic_bugfix_fhol_writev_fin_only_v2 = true; + QuicStreamId id = kClientDataStreamId1; + QuicStreamOffset offset = 0; + struct iovec iov; + string data; + + // This test will issue a write that will require fragmenting into + // multiple HTTP/2 DATA frames. It will ensure that only 1 frame + // will go out in the case that the underlying session becomes write + // blocked. Buffering is required to preserve framing, but the + // amount of buffering is limited to one HTTP/2 data frame. + const int kMinDataFrames = 4; + const size_t data_len = kSpdyInitialFrameSizeLimit * kMinDataFrames + 1024; + // Set headers stream send window large enough for data written below. + headers_stream_->flow_controller()->UpdateSendWindowOffset(data_len * 2 * 4); + test::GenerateBody(&data, data_len); + + bool fin = true; + // So force the underlying |WritevData| to consume only 1 byte. + // In that case, |WritevStreamData| should consume just one + // HTTP/2 data frame's worth of data. + EXPECT_CALL(session_, + WritevData(headers_stream_, kHeadersStreamId, _, _, false, _)) + .WillOnce( + WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIovShort))); + + QuicConsumedData consumed_data = headers_stream_->WritevStreamData( + id, MakeIOVector(data, &iov), offset, fin, nullptr); + + // bytes_consumed is max HTTP/2 data frame size minus the HTTP/2 + // data header size. + EXPECT_EQ(consumed_data.bytes_consumed, + kSpdyInitialFrameSizeLimit - + SpdyConstants::GetDataFrameMinimumSize(HTTP2)); + EXPECT_EQ(consumed_data.fin_consumed, false); + + // If session already blocked, then bytes_consumed should be zero. + consumed_data = headers_stream_->WritevStreamData( + id, MakeIOVector(data, &iov), offset, fin, nullptr); + + EXPECT_EQ(consumed_data.bytes_consumed, 0u); + EXPECT_EQ(consumed_data.fin_consumed, false); +} + } // namespace } // namespace test } // namespace net
diff --git a/net/quic/core/quic_session.cc b/net/quic/core/quic_session.cc index e3472b7..4df0b42 100644 --- a/net/quic/core/quic_session.cc +++ b/net/quic/core/quic_session.cc
@@ -162,6 +162,36 @@ << "Received BLOCKED frame with stream id: " << frame.stream_id; } +bool QuicSession::CheckStreamNotBusyLooping(ReliableQuicStream* stream, + uint64_t previous_bytes_written, + bool previous_fin_sent) { + if ( // Stream should not be closed. + !stream->write_side_closed() && + // Not connection flow control blocked. + !flow_controller_.IsBlocked() && + // Detect lack of forward progress. + previous_bytes_written == stream->stream_bytes_written() && + previous_fin_sent == stream->fin_sent()) { + stream->set_busy_counter(stream->busy_counter() + 1); + DVLOG(1) << "Suspected busy loop on stream id " << stream->id() + << " stream_bytes_written " << stream->stream_bytes_written() + << " fin " << stream->fin_sent() << " count " + << stream->busy_counter(); + // Wait a few iterations before firing, the exact count is + // arbitrary, more than a few to cover a few test-only false + // positives. + if (stream->busy_counter() > 20) { + LOG(ERROR) << "Detected busy loop on stream id " << stream->id() + << " stream_bytes_written " << stream->stream_bytes_written() + << " fin " << stream->fin_sent(); + return false; + } + } else { + stream->set_busy_counter(0); + } + return true; +} + void QuicSession::OnCanWrite() { // We limit the number of writes to the number of pending streams. If more // streams become pending, WillingAndAbleToWrite will be true, which will @@ -205,7 +235,13 @@ if (stream != nullptr && !stream->flow_controller()->IsBlocked()) { // If the stream can't write all bytes it'll re-add itself to the blocked // list. + uint64_t previous_bytes_written = stream->stream_bytes_written(); + bool previous_fin_sent = stream->fin_sent(); + DVLOG(1) << "stream " << stream->id() << " bytes_written " + << previous_bytes_written << " fin " << previous_fin_sent; stream->OnCanWrite(); + DCHECK(CheckStreamNotBusyLooping(stream, previous_bytes_written, + previous_fin_sent)); } currently_writing_stream_id_ = 0; }
diff --git a/net/quic/core/quic_session.h b/net/quic/core/quic_session.h index b0362f3..29b50033 100644 --- a/net/quic/core/quic_session.h +++ b/net/quic/core/quic_session.h
@@ -348,6 +348,12 @@ // control window in a negotiated config. Closes the connection if invalid. void OnNewSessionFlowControlWindow(QuicStreamOffset new_window); + // Debug helper for |OnCanWrite()|, check that OnStreamWrite() makes + // forward progress. Returns false if busy loop detected. + bool CheckStreamNotBusyLooping(ReliableQuicStream* stream, + uint64_t previous_bytes_written, + bool previous_fin_sent); + // Keep track of highest received byte offset of locally closed streams, while // waiting for a definitive final highest offset from the peer. std::map<QuicStreamId, QuicStreamOffset>
diff --git a/net/quic/core/quic_session_test.cc b/net/quic/core/quic_session_test.cc index 9af64d1..59250ee 100644 --- a/net/quic/core/quic_session_test.cc +++ b/net/quic/core/quic_session_test.cc
@@ -173,6 +173,11 @@ consumed = QuicSession::WritevData(stream, id, data, offset, fin, ack_notifier_delegate); } + stream->set_stream_bytes_written(stream->stream_bytes_written() + + consumed.bytes_consumed); + if (fin && consumed.fin_consumed) { + stream->set_fin_sent(true); + } QuicSessionPeer::GetWriteBlockedStreams(this)->UpdateBytesForStream( id, consumed.bytes_consumed); return consumed; @@ -187,8 +192,10 @@ if (stream->id() != kCryptoStreamId) { this->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); } - return WritevData(stream, stream->id(), MakeIOVector("not empty", &iov), 0, - true, nullptr); + QuicConsumedData consumed = + WritevData(stream, stream->id(), MakeIOVector("not empty", &iov), 0, + true, nullptr); + return consumed; } QuicConsumedData SendLargeFakeData(ReliableQuicStream* stream, int bytes) { @@ -389,6 +396,7 @@ } TEST_P(QuicSessionTestServer, OnCanWrite) { + session_.set_writev_consumes_all_data(true); TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority); TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority); TestStream* stream6 = session_.CreateOutgoingDynamicStream(kDefaultPriority); @@ -402,17 +410,27 @@ // Reregister, to test the loop limit. EXPECT_CALL(*stream2, OnCanWrite()) - .WillOnce(Invoke(&stream2_blocker, - &StreamBlocker::MarkConnectionLevelWriteBlocked)); + .WillOnce(DoAll(testing::IgnoreResult(Invoke( + CreateFunctor(&TestSession::SendStreamData, + base::Unretained(&session_), stream2))), + Invoke(&stream2_blocker, + &StreamBlocker::MarkConnectionLevelWriteBlocked))); // 2 will get called a second time as it didn't finish its block - EXPECT_CALL(*stream2, OnCanWrite()); - EXPECT_CALL(*stream6, OnCanWrite()); + EXPECT_CALL(*stream2, OnCanWrite()) + .WillOnce(testing::IgnoreResult( + Invoke(CreateFunctor(&TestSession::SendStreamData, + base::Unretained(&session_), stream2)))); + EXPECT_CALL(*stream6, OnCanWrite()) + .WillOnce(testing::IgnoreResult( + Invoke(CreateFunctor(&TestSession::SendStreamData, + base::Unretained(&session_), stream6)))); // 4 will not get called, as we exceeded the loop limit. session_.OnCanWrite(); EXPECT_TRUE(session_.WillingAndAbleToWrite()); } TEST_P(QuicSessionTestServer, TestBatchedWrites) { + session_.set_writev_consumes_all_data(true); TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority); TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority); TestStream* stream6 = session_.CreateOutgoingDynamicStream(kDefaultPriority); @@ -471,9 +489,12 @@ Invoke(&stream6_blocker, &StreamBlocker::MarkConnectionLevelWriteBlocked))); EXPECT_CALL(*stream6, OnCanWrite()) - .WillOnce(testing::IgnoreResult( - Invoke(CreateFunctor(&TestSession::SendLargeFakeData, - base::Unretained(&session_), stream4, 6000)))); + .WillOnce(DoAll(testing::IgnoreResult(Invoke( + CreateFunctor(&TestSession::SendStreamData, + base::Unretained(&session_), stream6))), + testing::IgnoreResult(Invoke(CreateFunctor( + &TestSession::SendLargeFakeData, + base::Unretained(&session_), stream4, 6000))))); session_.OnCanWrite(); // Stream4 alread did 6k worth of writes, so after doing another 12k it should @@ -542,6 +563,7 @@ } TEST_P(QuicSessionTestServer, OnCanWriteCongestionControlBlocks) { + session_.set_writev_consumes_all_data(true); InSequence s; // Drive congestion control manually. @@ -560,10 +582,16 @@ StreamBlocker stream2_blocker(&session_, stream2->id()); EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _)) .WillOnce(Return(QuicTime::Delta::Zero())); - EXPECT_CALL(*stream2, OnCanWrite()); + EXPECT_CALL(*stream2, OnCanWrite()) + .WillOnce(testing::IgnoreResult( + Invoke(CreateFunctor(&TestSession::SendStreamData, + base::Unretained(&session_), stream2)))); EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _)) .WillOnce(Return(QuicTime::Delta::Zero())); - EXPECT_CALL(*stream6, OnCanWrite()); + EXPECT_CALL(*stream6, OnCanWrite()) + .WillOnce(testing::IgnoreResult( + Invoke(CreateFunctor(&TestSession::SendStreamData, + base::Unretained(&session_), stream6)))); EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _)) .WillOnce(Return(QuicTime::Delta::Infinite())); // stream4->OnCanWrite is not called. @@ -581,7 +609,10 @@ // congestion-control blocked. EXPECT_CALL(*send_algorithm, TimeUntilSend(_, _)) .WillOnce(Return(QuicTime::Delta::Zero())); - EXPECT_CALL(*stream4, OnCanWrite()); + EXPECT_CALL(*stream4, OnCanWrite()) + .WillOnce(testing::IgnoreResult( + Invoke(CreateFunctor(&TestSession::SendStreamData, + base::Unretained(&session_), stream4)))); EXPECT_CALL(*send_algorithm, OnApplicationLimited(_)); session_.OnCanWrite(); EXPECT_FALSE(session_.WillingAndAbleToWrite()); @@ -616,6 +647,7 @@ } TEST_P(QuicSessionTestServer, BufferedHandshake) { + session_.set_writev_consumes_all_data(true); EXPECT_FALSE(session_.HasPendingHandshake()); // Default value. // Test that blocking other streams does not change our status. @@ -648,11 +680,20 @@ TestCryptoStream* crypto_stream = session_.GetCryptoStream(); EXPECT_CALL(*crypto_stream, OnCanWrite()); - EXPECT_CALL(*stream2, OnCanWrite()); - EXPECT_CALL(*stream3, OnCanWrite()); + EXPECT_CALL(*stream2, OnCanWrite()) + .WillOnce(testing::IgnoreResult( + Invoke(CreateFunctor(&TestSession::SendStreamData, + base::Unretained(&session_), stream2)))); + EXPECT_CALL(*stream3, OnCanWrite()) + .WillOnce(testing::IgnoreResult( + Invoke(CreateFunctor(&TestSession::SendStreamData, + base::Unretained(&session_), stream3)))); EXPECT_CALL(*stream4, OnCanWrite()) - .WillOnce(Invoke(&stream4_blocker, - &StreamBlocker::MarkConnectionLevelWriteBlocked)); + .WillOnce(DoAll(testing::IgnoreResult(Invoke( + CreateFunctor(&TestSession::SendStreamData, + base::Unretained(&session_), stream4))), + Invoke(&stream4_blocker, + &StreamBlocker::MarkConnectionLevelWriteBlocked))); session_.OnCanWrite(); EXPECT_TRUE(session_.WillingAndAbleToWrite()); @@ -660,6 +701,7 @@ } TEST_P(QuicSessionTestServer, OnCanWriteWithClosedStream) { + session_.set_writev_consumes_all_data(true); TestStream* stream2 = session_.CreateOutgoingDynamicStream(kDefaultPriority); TestStream* stream4 = session_.CreateOutgoingDynamicStream(kDefaultPriority); TestStream* stream6 = session_.CreateOutgoingDynamicStream(kDefaultPriority); @@ -670,8 +712,14 @@ CloseStream(stream6->id()); InSequence s; - EXPECT_CALL(*stream2, OnCanWrite()); - EXPECT_CALL(*stream4, OnCanWrite()); + EXPECT_CALL(*stream2, OnCanWrite()) + .WillOnce(testing::IgnoreResult( + Invoke(CreateFunctor(&TestSession::SendStreamData, + base::Unretained(&session_), stream2)))); + EXPECT_CALL(*stream4, OnCanWrite()) + .WillOnce(testing::IgnoreResult( + Invoke(CreateFunctor(&TestSession::SendStreamData, + base::Unretained(&session_), stream4)))); session_.OnCanWrite(); EXPECT_FALSE(session_.WillingAndAbleToWrite()); }
diff --git a/net/quic/core/quic_spdy_session.cc b/net/quic/core/quic_spdy_session.cc index 37a165c..c4b7b0e 100644 --- a/net/quic/core/quic_spdy_session.cc +++ b/net/quic/core/quic_spdy_session.cc
@@ -157,12 +157,24 @@ const QuicVersion version = connection()->version(); if (version > QUIC_VERSION_35 && config()->ForceHolBlocking(perspective())) { force_hol_blocking_ = true; - // Autotuning makes sure that the headers stream flow control does - // not get in the way, and normal stream and connection level flow - // control are active anyway. This is really only for the client - // side (and mainly there just in tests and toys), where - // autotuning and/or large buffers are not enabled by default. - headers_stream_->flow_controller()->set_auto_tune_receive_window(true); + if (!FLAGS_quic_bugfix_fhol_writev_fin_only_v2) { + // Autotuning makes sure that the headers stream flow control does + // not get in the way, and normal stream and connection level flow + // control are active anyway. This is really only for the client + // side (and mainly there just in tests and toys), where + // autotuning and/or large buffers are not enabled by default. + headers_stream_->flow_controller()->set_auto_tune_receive_window(true); + } else { + // Since all streams are tunneled through the headers stream, it + // is important that headers stream never flow control blocks. + // Otherwise, busy-loop behaviour can ensue where data streams + // data try repeatedly to write data not realizing that the + // tunnel through the headers stream is blocked. + headers_stream_->flow_controller()->UpdateReceiveWindowSize( + kStreamReceiveWindowLimit); + headers_stream_->flow_controller()->UpdateSendWindowOffset( + kStreamReceiveWindowLimit); + } } if (version > QUIC_VERSION_34) {
diff --git a/net/quic/core/quic_spdy_stream_test.cc b/net/quic/core/quic_spdy_stream_test.cc index c1ced63..870f3b8 100644 --- a/net/quic/core/quic_spdy_stream_test.cc +++ b/net/quic/core/quic_spdy_stream_test.cc
@@ -197,40 +197,40 @@ int status_code = 0; // Valid status code. - headers_.ReplaceOrAppendHeader(":status", "404"); + headers_[":status"] = "404"; EXPECT_TRUE(stream_->ParseHeaderStatusCode(headers_, &status_code)); EXPECT_EQ(404, status_code); // Invalid status codes. - headers_.ReplaceOrAppendHeader(":status", "010"); + headers_[":status"] = "010"; EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code)); - headers_.ReplaceOrAppendHeader(":status", "600"); + headers_[":status"] = "600"; EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code)); - headers_.ReplaceOrAppendHeader(":status", "200 ok"); + headers_[":status"] = "200 ok"; EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code)); - headers_.ReplaceOrAppendHeader(":status", "2000"); + headers_[":status"] = "2000"; EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code)); - headers_.ReplaceOrAppendHeader(":status", "+200"); + headers_[":status"] = "+200"; EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code)); - headers_.ReplaceOrAppendHeader(":status", "+20"); + headers_[":status"] = "+20"; EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code)); // Leading or trailing spaces are also invalid. - headers_.ReplaceOrAppendHeader(":status", " 200"); + headers_[":status"] = " 200"; EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code)); - headers_.ReplaceOrAppendHeader(":status", "200 "); + headers_[":status"] = "200 "; EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code)); - headers_.ReplaceOrAppendHeader(":status", " 200 "); + headers_[":status"] = " 200 "; EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code)); - headers_.ReplaceOrAppendHeader(":status", " "); + headers_[":status"] = " "; EXPECT_FALSE(stream_->ParseHeaderStatusCode(headers_, &status_code)); }
diff --git a/net/quic/core/reliable_quic_stream.cc b/net/quic/core/reliable_quic_stream.cc index 740f161..79880dc 100644 --- a/net/quic/core/reliable_quic_stream.cc +++ b/net/quic/core/reliable_quic_stream.cc
@@ -74,7 +74,8 @@ GetInitialStreamFlowControlWindowToSend(session), session_->flow_controller()->auto_tune_receive_window()), connection_flow_controller_(session_->flow_controller()), - stream_contributes_to_connection_flow_control_(true) { + stream_contributes_to_connection_flow_control_(true), + busy_counter_(0) { SetFromConfig(); } @@ -303,6 +304,8 @@ // Writing more data would be a violation of flow control. write_length = static_cast<size_t>(send_window); + DVLOG(1) << "stream " << id() << " shortens write length to " + << write_length << " due to flow control"; } QuicConsumedData consumed_data =
diff --git a/net/quic/core/reliable_quic_stream.h b/net/quic/core/reliable_quic_stream.h index 2122e866..a1e3df2 100644 --- a/net/quic/core/reliable_quic_stream.h +++ b/net/quic/core/reliable_quic_stream.h
@@ -111,6 +111,13 @@ uint64_t stream_bytes_read() const { return stream_bytes_read_; } uint64_t stream_bytes_written() const { return stream_bytes_written_; } + // For tests that override WritevData. + void set_stream_bytes_written(uint64_t bytes_written) { + stream_bytes_written_ = bytes_written; + } + + size_t busy_counter() const { return busy_counter_; } + void set_busy_counter(size_t busy_counter) { busy_counter_ = busy_counter; } void set_fin_sent(bool fin_sent) { fin_sent_ = fin_sent; } void set_fin_received(bool fin_received) { fin_received_ = fin_received; } @@ -303,6 +310,9 @@ // limited). bool stream_contributes_to_connection_flow_control_; + // For debugging only, used for busy loop check. + size_t busy_counter_; + DISALLOW_COPY_AND_ASSIGN(ReliableQuicStream); };
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc index 9770a65..69258e3 100644 --- a/net/socket/ssl_client_socket_impl.cc +++ b/net/socket/ssl_client_socket_impl.cc
@@ -112,8 +112,14 @@ case SSLPrivateKey::Type::RSA: type_str = "RSA"; break; - case SSLPrivateKey::Type::ECDSA: - type_str = "ECDSA"; + case SSLPrivateKey::Type::ECDSA_P256: + type_str = "ECDSA_P256"; + break; + case SSLPrivateKey::Type::ECDSA_P384: + type_str = "ECDSA_P384"; + break; + case SSLPrivateKey::Type::ECDSA_P521: + type_str = "ECDSA_P521"; break; } @@ -2009,12 +2015,16 @@ int SSLClientSocketImpl::PrivateKeyTypeCallback() { switch (ssl_config_.client_private_key->GetType()) { case SSLPrivateKey::Type::RSA: - return EVP_PKEY_RSA; - case SSLPrivateKey::Type::ECDSA: - return EVP_PKEY_EC; + return NID_rsaEncryption; + case SSLPrivateKey::Type::ECDSA_P256: + return NID_X9_62_prime256v1; + case SSLPrivateKey::Type::ECDSA_P384: + return NID_secp384r1; + case SSLPrivateKey::Type::ECDSA_P521: + return NID_secp521r1; } NOTREACHED(); - return EVP_PKEY_NONE; + return NID_undef; } size_t SSLClientSocketImpl::PrivateKeyMaxSignatureLenCallback() {
diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc index 82c8f35..8f22947 100644 --- a/net/socket/ssl_server_socket_unittest.cc +++ b/net/socket/ssl_server_socket_unittest.cc
@@ -549,17 +549,19 @@ ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info)); EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, ssl_info.cert_status); - // The default cipher suite should be ECDHE and, unless on NSS and the - // platform doesn't support it, an AEAD. + // The default cipher suite should be ECDHE and an AEAD. uint16_t cipher_suite = SSLConnectionStatusToCipherSuite(ssl_info.connection_status); const char* key_exchange; const char* cipher; const char* mac; bool is_aead; - SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, cipher_suite); - EXPECT_STREQ("ECDHE_RSA", key_exchange); + bool is_tls13; + SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, + cipher_suite); EXPECT_TRUE(is_aead); + ASSERT_FALSE(is_tls13); + EXPECT_STREQ("ECDHE_RSA", key_exchange); } // This test makes sure the session cache is working.
diff --git a/net/spdy/header_coalescer.cc b/net/spdy/header_coalescer.cc index 199fabf4..24bd9cb 100644 --- a/net/spdy/header_coalescer.cc +++ b/net/spdy/header_coalescer.cc
@@ -60,7 +60,7 @@ base::StringPiece("\0", 1).AppendToString(&s); } value.AppendToString(&s); - headers_.ReplaceOrAppendHeader(key, s); + headers_[key] = s; } }
diff --git a/net/spdy/spdy_header_block.cc b/net/spdy/spdy_header_block.cc index 20ddee48..ffa62fe 100644 --- a/net/spdy/spdy_header_block.cc +++ b/net/spdy/spdy_header_block.cc
@@ -190,7 +190,16 @@ void SpdyHeaderBlock::insert( const SpdyHeaderBlock::MapType::value_type& value) { - ReplaceOrAppendHeader(value.first, value.second); + // TODO(birenroy): Write new value in place of old value, if it fits. + auto iter = block_.find(value.first); + if (iter == block_.end()) { + DVLOG(1) << "Inserting: (" << value.first << ", " << value.second << ")"; + AppendHeader(value.first, value.second); + } else { + DVLOG(1) << "Updating key: " << iter->first + << " with value: " << value.second; + iter->second = GetStorage()->Write(value.second); + } } SpdyHeaderBlock::StringPieceProxy SpdyHeaderBlock::operator[]( @@ -216,19 +225,6 @@ return iter == block_.end() ? StringPiece() : iter->second; } -void SpdyHeaderBlock::ReplaceOrAppendHeader(const StringPiece key, - const StringPiece value) { - // TODO(birenroy): Write new value in place of old value, if it fits. - auto iter = block_.find(key); - if (iter == block_.end()) { - DVLOG(1) << "Inserting: (" << key << ", " << value << ")"; - AppendHeader(key, value); - } else { - DVLOG(1) << "Updating key: " << iter->first << " with value: " << value; - iter->second = GetStorage()->Write(value); - } -} - void SpdyHeaderBlock::AppendValueOrAddHeader(const StringPiece key, const StringPiece value) { auto iter = block_.find(key);
diff --git a/net/spdy/spdy_header_block.h b/net/spdy/spdy_header_block.h index b0d5734..89248499f 100644 --- a/net/spdy/spdy_header_block.h +++ b/net/spdy/spdy_header_block.h
@@ -96,11 +96,6 @@ // adds a new header to the end of the block. void insert(const MapType::value_type& value); - // If key already exists in the block, replaces the value of that key. Else - // adds a new header to the end of the block. - void ReplaceOrAppendHeader(const base::StringPiece key, - const base::StringPiece value); - // If a header with the key is already present, then append the value to the // existing header value, NUL ("\0") separated unless the key is cookie, in // which case the separator is "; ".
diff --git a/net/spdy/spdy_header_block_test.cc b/net/spdy/spdy_header_block_test.cc index e57f00b..53e7306 100644 --- a/net/spdy/spdy_header_block_test.cc +++ b/net/spdy/spdy_header_block_test.cc
@@ -79,7 +79,7 @@ SpdyHeaderBlock block; block["foo"] = string(300, 'x'); block["bar"] = "baz"; - block.ReplaceOrAppendHeader("qux", "qux1"); + block["qux"] = "qux1"; block["qux"] = "qux2"; block.insert(std::make_pair("key", "value")); @@ -101,7 +101,7 @@ SpdyHeaderBlock block1; block1["foo"] = string(300, 'x'); block1["bar"] = "baz"; - block1.ReplaceOrAppendHeader("qux", "qux1"); + block1.insert(make_pair("qux", "qux1")); SpdyHeaderBlock block2 = block1.Clone(); SpdyHeaderBlock block3(block1.Clone()); @@ -149,15 +149,15 @@ SpdyHeaderBlock block2(std::move(block1)); EXPECT_THAT(block2, ElementsAre(Pair("foo", "bar"))); - block1.ReplaceOrAppendHeader("baz", "qux"); + block1["baz"] = "qux"; // NOLINT testing post-move behavior SpdyHeaderBlock block3(std::move(block1)); - block1["foo"] = "bar"; + block1["foo"] = "bar"; // NOLINT testing post-move behavior SpdyHeaderBlock block4(std::move(block1)); - block1.clear(); + block1.clear(); // NOLINT testing post-move behavior EXPECT_TRUE(block1.empty()); block1["foo"] = "bar"; @@ -180,15 +180,12 @@ block["cookie"] = "key1=value1"; block.AppendValueOrAddHeader("h1", "h1v1"); block.insert(std::make_pair("h2", "h2v1")); - block.ReplaceOrAppendHeader("h3", "h3v1"); block.AppendValueOrAddHeader("h3", "h3v2"); block.AppendValueOrAddHeader("h2", "h2v2"); block.AppendValueOrAddHeader("h1", "h1v2"); block.AppendValueOrAddHeader("cookie", "key2=value2"); - block.ReplaceOrAppendHeader("h4", "h4v1"); - block.AppendValueOrAddHeader("cookie", "key3=value3"); block.AppendValueOrAddHeader("h1", "h1v3"); block.AppendValueOrAddHeader("h2", "h2v3"); @@ -198,8 +195,7 @@ EXPECT_EQ("baz", block["foo"]); EXPECT_EQ(string("h1v1\0h1v2\0h1v3", 14), block["h1"]); EXPECT_EQ(string("h2v1\0h2v2\0h2v3", 14), block["h2"]); - EXPECT_EQ(string("h3v1\0h3v2\0h3v3", 14), block["h3"]); - EXPECT_EQ("h4v1", block["h4"]); + EXPECT_EQ(string("h3v2\0h3v3", 9), block["h3"]); } } // namespace test
diff --git a/net/ssl/ssl_cipher_suite_names.cc b/net/ssl/ssl_cipher_suite_names.cc index ba2129aa0..24f54fc0d 100644 --- a/net/ssl/ssl_cipher_suite_names.cc +++ b/net/ssl/ssl_cipher_suite_names.cc
@@ -129,6 +129,9 @@ {0xc3, 0x85b}, // TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 {0xc4, 0xa5b}, // TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 {0xc5, 0xc5b}, // TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 + {0x1301, 0x1f6f}, // TLS_AES_128_GCM_SHA256 + {0x1302, 0x1f77}, // TLS_AES_256_GCM_SHA384 + {0x1303, 0x1f8f}, // TLS_CHACHA20_POLY1305_SHA256 {0x16b7, 0x128f}, // TLS_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256 (exper) {0x16b8, 0x138f}, // TLS_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (exper) {0x16b9, 0x1277}, // TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384 (exper) @@ -206,37 +209,36 @@ {0xcc14, 0x0e8f}, // TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 (non-standard) {0xcca8, 0x108f}, // TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 {0xcca9, 0x0e8f}, // TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 - {0xccab, 0x148f}, // TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 - {0xd001, 0x146f}, // TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 - {0xd002, 0x1477}, // TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384 }; const struct { char name[15]; -} kKeyExchangeNames[21] = { - {"NULL"}, // 0 - {"RSA"}, // 1 - {"RSA_EXPORT"}, // 2 - {"DH_DSS_EXPORT"}, // 3 - {"DH_DSS"}, // 4 - {"DH_RSA_EXPORT"}, // 5 - {"DH_RSA"}, // 6 - {"DHE_DSS_EXPORT"}, // 7 - {"DHE_DSS"}, // 8 - {"DHE_RSA_EXPORT"}, // 9 - {"DHE_RSA"}, // 10 - {"DH_anon_EXPORT"}, // 11 - {"DH_anon"}, // 12 - {"ECDH_ECDSA"}, // 13 - {"ECDHE_ECDSA"}, // 14 - {"ECDH_RSA"}, // 15 - {"ECDHE_RSA"}, // 16 - {"ECDH_anon"}, // 17 - {"CECPQ1_RSA"}, // 18 - {"CECPQ1_ECDSA"}, // 19 - {"ECDHE_PSK"}, // 20 +} kKeyExchangeNames[20] = { + {"NULL"}, // 0 + {"RSA"}, // 1 + {"RSA_EXPORT"}, // 2 + {"DH_DSS_EXPORT"}, // 3 + {"DH_DSS"}, // 4 + {"DH_RSA_EXPORT"}, // 5 + {"DH_RSA"}, // 6 + {"DHE_DSS_EXPORT"}, // 7 + {"DHE_DSS"}, // 8 + {"DHE_RSA_EXPORT"}, // 9 + {"DHE_RSA"}, // 10 + {"DH_anon_EXPORT"}, // 11 + {"DH_anon"}, // 12 + {"ECDH_ECDSA"}, // 13 + {"ECDHE_ECDSA"}, // 14 + {"ECDH_RSA"}, // 15 + {"ECDHE_RSA"}, // 16 + {"ECDH_anon"}, // 17 + {"CECPQ1_RSA"}, // 18 + {"CECPQ1_ECDSA"}, // 19 + // 31 is reserved to indicate a TLS 1.3 AEAD-only suite. }; +constexpr int kTLS13KeyExchangeValue = 31; + const struct { char name[18]; } kCipherNames[18] = { @@ -323,13 +325,12 @@ return obsolete_ssl; } - // Only allow ECDHE key exchanges. switch (key_exchange) { case 14: // ECDHE_ECDSA case 16: // ECDHE_RSA case 18: // CECPQ1_RSA case 19: // CECPQ1_ECDSA - case 20: // ECDHE_PSK + case kTLS13KeyExchangeValue: // TLS 1.3 break; default: obsolete_ssl |= net::OBSOLETE_SSL_MASK_KEY_EXCHANGE; @@ -359,19 +360,26 @@ const char** cipher_str, const char** mac_str, bool* is_aead, + bool* is_tls13, uint16_t cipher_suite) { *key_exchange_str = *cipher_str = *mac_str = "???"; *is_aead = false; + *is_tls13 = false; int key_exchange, cipher, mac; if (!GetCipherProperties(cipher_suite, &key_exchange, &cipher, &mac)) return; - *key_exchange_str = kKeyExchangeNames[key_exchange].name; + if (key_exchange == kTLS13KeyExchangeValue) { + *key_exchange_str = nullptr; + *is_tls13 = true; + } else { + *key_exchange_str = kKeyExchangeNames[key_exchange].name; + } *cipher_str = kCipherNames[cipher].name; if (mac == kAEADMACValue) { *is_aead = true; - *mac_str = NULL; + *mac_str = nullptr; } else { *mac_str = kMacNames[mac].name; } @@ -444,7 +452,7 @@ case 16: // ECDHE_RSA case 18: // CECPQ1_RSA case 19: // CECPQ1_ECDSA - case 20: // ECDHE_PSK + case kTLS13KeyExchangeValue: // TLS 1.3 break; default: return false;
diff --git a/net/ssl/ssl_cipher_suite_names.h b/net/ssl/ssl_cipher_suite_names.h index 7c1192b..36a6d152 100644 --- a/net/ssl/ssl_cipher_suite_names.h +++ b/net/ssl/ssl_cipher_suite_names.h
@@ -19,11 +19,15 @@ // wire and recorded at // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml // If the cipher suite is unknown, the strings are set to "???". -// In the case of an AEAD cipher suite, *mac_str is NULL and *is_aead is true. +// In the case of an AEAD cipher suite, *mac_str is nullptr and *is_aead is +// true. +// In the case of a TLS 1.3 AEAD-only cipher suite, *key_exchange_str is nullptr +// and *is_tls13 is true. NET_EXPORT void SSLCipherSuiteToStrings(const char** key_exchange_str, const char** cipher_str, const char** mac_str, bool* is_aead, + bool* is_tls13, uint16_t cipher_suite); // SSLVersionToString returns the name of the SSL protocol version
diff --git a/net/ssl/ssl_cipher_suite_names_unittest.cc b/net/ssl/ssl_cipher_suite_names_unittest.cc index 83eb55c..5bda4c7 100644 --- a/net/ssl/ssl_cipher_suite_names_unittest.cc +++ b/net/ssl/ssl_cipher_suite_names_unittest.cc
@@ -39,38 +39,72 @@ TEST(CipherSuiteNamesTest, Basic) { const char *key_exchange, *cipher, *mac; - bool is_aead; + bool is_aead, is_tls13; - SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, 0xc001); + SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, + 0xc001); EXPECT_STREQ("ECDH_ECDSA", key_exchange); EXPECT_STREQ("NULL", cipher); EXPECT_STREQ("HMAC-SHA1", mac); EXPECT_FALSE(is_aead); + EXPECT_FALSE(is_tls13); - SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, 0x009f); + SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, + 0x009f); EXPECT_STREQ("DHE_RSA", key_exchange); EXPECT_STREQ("AES_256_GCM", cipher); EXPECT_TRUE(is_aead); - EXPECT_EQ(NULL, mac); + EXPECT_FALSE(is_tls13); + EXPECT_EQ(nullptr, mac); - SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, 0xcca9); + SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, + 0xcca9); EXPECT_STREQ("ECDHE_ECDSA", key_exchange); EXPECT_STREQ("CHACHA20_POLY1305", cipher); EXPECT_TRUE(is_aead); - EXPECT_EQ(NULL, mac); + EXPECT_FALSE(is_tls13); + EXPECT_EQ(nullptr, mac); // Non-standard variant. - SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, 0xcc14); + SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, + 0xcc14); EXPECT_STREQ("ECDHE_ECDSA", key_exchange); EXPECT_STREQ("CHACHA20_POLY1305", cipher); EXPECT_TRUE(is_aead); - EXPECT_EQ(NULL, mac); + EXPECT_FALSE(is_tls13); + EXPECT_EQ(nullptr, mac); - SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, 0xff31); + SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, + 0xff31); EXPECT_STREQ("???", key_exchange); EXPECT_STREQ("???", cipher); EXPECT_STREQ("???", mac); EXPECT_FALSE(is_aead); + EXPECT_FALSE(is_tls13); + + SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, + 0x1301); + EXPECT_STREQ("AES_128_GCM", cipher); + EXPECT_TRUE(is_aead); + EXPECT_TRUE(is_tls13); + EXPECT_EQ(nullptr, mac); + EXPECT_EQ(nullptr, key_exchange); + + SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, + 0x1302); + EXPECT_STREQ("AES_256_GCM", cipher); + EXPECT_TRUE(is_aead); + EXPECT_TRUE(is_tls13); + EXPECT_EQ(nullptr, mac); + EXPECT_EQ(nullptr, key_exchange); + + SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, + 0x1303); + EXPECT_STREQ("CHACHA20_POLY1305", cipher); + EXPECT_TRUE(is_aead); + EXPECT_TRUE(is_tls13); + EXPECT_EQ(nullptr, mac); + EXPECT_EQ(nullptr, key_exchange); } TEST(CipherSuiteNamesTest, ParseSSLCipherString) { @@ -147,6 +181,9 @@ EXPECT_EQ(OBSOLETE_SSL_NONE, ObsoleteSSLStatus(MakeConnectionStatus( kModernVersion, kModernCipherModernKeyExchange))); + EXPECT_EQ(OBSOLETE_SSL_NONE, ObsoleteSSLStatus(MakeConnectionStatus( + SSL_CONNECTION_VERSION_TLS1_3, + 0x1301 /* AES_128_GCM_SHA256 */))); } TEST(CipherSuiteNamesTest, HTTP2CipherSuites) { @@ -182,6 +219,9 @@ 0xcca8 /* ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */)); EXPECT_TRUE(IsTLSCipherSuiteAllowedByHTTP2( 0xcca9 /* ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 */)); + EXPECT_TRUE(IsTLSCipherSuiteAllowedByHTTP2(0x1301 /* AES_128_GCM_SHA256 */)); + EXPECT_TRUE(IsTLSCipherSuiteAllowedByHTTP2(0x1302 /* AES_256_GCM_SHA384 */)); + EXPECT_TRUE(IsTLSCipherSuiteAllowedByHTTP2(0x1303 /* CHACHA20_POLY1305 */)); } TEST(CipherSuiteNamesTest, CECPQ1) { @@ -192,7 +232,7 @@ 0x16ba, // TLS_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384 (non-standard) }; const char *key_exchange, *cipher, *mac; - bool is_aead; + bool is_aead, is_tls13; for (const uint16_t cipher_suite_id : kCECPQ1CipherSuites) { SCOPED_TRACE(base::StringPrintf("cipher suite %x", cipher_suite_id)); @@ -201,25 +241,31 @@ int connection_status = MakeConnectionStatus(kModernVersion, cipher_suite_id); EXPECT_EQ(OBSOLETE_SSL_NONE, ObsoleteSSLStatus(connection_status)); - SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, + EXPECT_TRUE(IsTLSCipherSuiteAllowedByHTTP2(cipher_suite_id)); + SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, cipher_suite_id); EXPECT_TRUE(is_aead); + EXPECT_FALSE(is_tls13); EXPECT_EQ(nullptr, mac); } - SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, 0x16b7); + SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, + 0x16b7); EXPECT_STREQ("CECPQ1_RSA", key_exchange); EXPECT_STREQ("CHACHA20_POLY1305", cipher); - SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, 0x16b8); + SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, + 0x16b8); EXPECT_STREQ("CECPQ1_ECDSA", key_exchange); EXPECT_STREQ("CHACHA20_POLY1305", cipher); - SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, 0x16b9); + SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, + 0x16b9); EXPECT_STREQ("CECPQ1_RSA", key_exchange); EXPECT_STREQ("AES_256_GCM", cipher); - SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, 0x16ba); + SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, + 0x16ba); EXPECT_STREQ("CECPQ1_ECDSA", key_exchange); EXPECT_STREQ("AES_256_GCM", cipher); }
diff --git a/net/ssl/ssl_platform_key_android.cc b/net/ssl/ssl_platform_key_android.cc index ef9df17..e6bc349 100644 --- a/net/ssl/ssl_platform_key_android.cc +++ b/net/ssl/ssl_platform_key_android.cc
@@ -25,7 +25,7 @@ #include "net/base/net_errors.h" #include "net/ssl/openssl_client_key_store.h" #include "net/ssl/ssl_platform_key.h" -#include "net/ssl/ssl_platform_key_task_runner.h" +#include "net/ssl/ssl_platform_key_util.h" #include "net/ssl/threaded_ssl_private_key.h" using base::android::JavaRef; @@ -176,88 +176,50 @@ DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyAndroid); }; -// VectorBignumSize returns the number of bytes needed to represent the bignum -// given in |v|, i.e. the length of |v| less any leading zero bytes. -size_t VectorBignumSize(const std::vector<uint8_t>& v) { - size_t size = v.size(); - // Ignore any leading zero bytes. - for (size_t i = 0; i < v.size() && v[i] == 0; i++) { - size--; - } - return size; -} +} // namespace -std::unique_ptr<SSLPlatformKeyAndroid> CreateRsaKey( +scoped_refptr<SSLPrivateKey> WrapJavaPrivateKey( + const X509Certificate* certificate, const JavaRef<jobject>& key) { + SSLPrivateKey::Type type; + size_t max_length; + if (!GetClientCertInfo(certificate, &type, &max_length)) + return nullptr; + android::AndroidRSA* sys_rsa = nullptr; - const int kAndroid42ApiLevel = 17; - if (base::android::BuildInfo::GetInstance()->sdk_int() < kAndroid42ApiLevel) { - // Route around platform limitations: if Android < 4.2, then - // base::android::RawSignDigestWithPrivateKey() cannot work, so try to get - // the system OpenSSL's EVP_PKEY backing this PrivateKey object. - android::AndroidEVP_PKEY* sys_pkey = - android::GetOpenSSLSystemHandleForPrivateKey(key); - if (!sys_pkey) - return nullptr; + if (type == SSLPrivateKey::Type::RSA) { + const int kAndroid42ApiLevel = 17; + if (base::android::BuildInfo::GetInstance()->sdk_int() < + kAndroid42ApiLevel) { + // Route around platform limitations: if Android < 4.2, then + // base::android::RawSignDigestWithPrivateKey() cannot work, so try to get + // the system OpenSSL's EVP_PKEY backing this PrivateKey object. + android::AndroidEVP_PKEY* sys_pkey = + android::GetOpenSSLSystemHandleForPrivateKey(key); + if (!sys_pkey) + return nullptr; - if (sys_pkey->type != android::ANDROID_EVP_PKEY_RSA) { - LOG(ERROR) << "Private key has wrong type!"; - return nullptr; - } + if (sys_pkey->type != android::ANDROID_EVP_PKEY_RSA) { + LOG(ERROR) << "Private key has wrong type!"; + return nullptr; + } - sys_rsa = sys_pkey->pkey.rsa; - if (sys_rsa->engine) { - // |private_key| may not have an engine if the PrivateKey did not come - // from the key store, such as in unit tests. - if (strcmp(sys_rsa->engine->id, "keystore") == 0) { - LeakEngine(key); - } else { - NOTREACHED(); + sys_rsa = sys_pkey->pkey.rsa; + if (sys_rsa->engine) { + // |private_key| may not have an engine if the PrivateKey did not come + // from the key store, such as in unit tests. + if (strcmp(sys_rsa->engine->id, "keystore") == 0) { + LeakEngine(key); + } else { + NOTREACHED(); + } } } } - std::vector<uint8_t> modulus; - if (!android::GetRSAKeyModulus(key, &modulus)) { - LOG(ERROR) << "Failed to get private key modulus"; - return nullptr; - } - - return base::MakeUnique<SSLPlatformKeyAndroid>( - SSLPrivateKey::Type::RSA, key, VectorBignumSize(modulus), sys_rsa); -} - -std::unique_ptr<SSLPlatformKeyAndroid> CreateEcdsaKey( - const JavaRef<jobject>& key) { - std::vector<uint8_t> order; - if (!android::GetECKeyOrder(key, &order)) { - LOG(ERROR) << "Can't extract order parameter from EC private key"; - return nullptr; - } - - return base::MakeUnique<SSLPlatformKeyAndroid>( - SSLPrivateKey::Type::ECDSA, key, - ECDSA_SIG_max_len(VectorBignumSize(order)), nullptr); -} - -} // namespace - -scoped_refptr<SSLPrivateKey> WrapJavaPrivateKey(const JavaRef<jobject>& key) { - std::unique_ptr<SSLPlatformKeyAndroid> delegate; - switch (android::GetPrivateKeyType(key)) { - case android::PRIVATE_KEY_TYPE_RSA: - delegate = CreateRsaKey(key); - break; - case android::PRIVATE_KEY_TYPE_ECDSA: - delegate = CreateEcdsaKey(key); - break; - default: - LOG(WARNING) << "GetPrivateKeyType() returned invalid type"; - return nullptr; - } - return make_scoped_refptr(new ThreadedSSLPrivateKey( - std::move(delegate), GetSSLPlatformKeyTaskRunner())); + base::MakeUnique<SSLPlatformKeyAndroid>(type, key, max_length, sys_rsa), + GetSSLPlatformKeyTaskRunner())); } scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(
diff --git a/net/ssl/ssl_platform_key_android.h b/net/ssl/ssl_platform_key_android.h index 95fe90a9..c025955 100644 --- a/net/ssl/ssl_platform_key_android.h +++ b/net/ssl/ssl_platform_key_android.h
@@ -14,10 +14,13 @@ namespace net { class SSLPrivateKey; +class X509Certificate; -// Returns a new SSLPrivateKey which uses |key| for signing operations or -// nullptr on error. |key| must be a java.security.PrivateKey object. +// Returns a new SSLPrivateKey for |cert| which uses |key| for signing +// operations or nullptr on error. |key| must be a java.security.PrivateKey +// object. NET_EXPORT scoped_refptr<SSLPrivateKey> WrapJavaPrivateKey( + const X509Certificate* cert, const base::android::JavaRef<jobject>& key); } // namespace net
diff --git a/net/ssl/ssl_platform_key_android_unittest.cc b/net/ssl/ssl_platform_key_android_unittest.cc index 260597a..2adaaa4 100644 --- a/net/ssl/ssl_platform_key_android_unittest.cc +++ b/net/ssl/ssl_platform_key_android_unittest.cc
@@ -109,6 +109,7 @@ } const char kTestRsaKeyFile[] = "client_1.pk8"; +const char kTestRsaCertificateFile[] = "client_1.pem"; // Retrieve a JNI local ref for our test RSA key. ScopedJava GetRSATestKeyJava() { @@ -287,10 +288,14 @@ TEST(SSLPlatformKeyAndroid, RSA) { crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); + scoped_refptr<X509Certificate> cert = + ImportCertFromFile(GetTestCertsDirectory(), kTestRsaCertificateFile); + ASSERT_TRUE(cert); ScopedJava rsa_key = GetRSATestKeyJava(); ASSERT_FALSE(rsa_key.is_null()); - scoped_refptr<SSLPrivateKey> wrapper_key = WrapJavaPrivateKey(rsa_key); + scoped_refptr<SSLPrivateKey> wrapper_key = + WrapJavaPrivateKey(cert.get(), rsa_key); ASSERT_TRUE(wrapper_key); bssl::UniquePtr<EVP_PKEY> openssl_key = ImportPrivateKeyFile(kTestRsaKeyFile); @@ -319,10 +324,14 @@ TEST(SSLPlatformKeyAndroid, ECDSA) { crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); + scoped_refptr<X509Certificate> cert = + ImportCertFromFile(GetTestCertsDirectory(), kTestEcdsaCertificateFile); + ASSERT_TRUE(cert); ScopedJava ecdsa_key = GetECDSATestKeyJava(); ASSERT_FALSE(ecdsa_key.is_null()); - scoped_refptr<SSLPrivateKey> wrapper_key = WrapJavaPrivateKey(ecdsa_key); + scoped_refptr<SSLPrivateKey> wrapper_key = + WrapJavaPrivateKey(cert.get(), ecdsa_key); ASSERT_TRUE(wrapper_key); bssl::UniquePtr<EVP_PKEY> openssl_key = @@ -330,7 +339,7 @@ ASSERT_TRUE(openssl_key); // Check that the wrapper key returns the correct length and type. - EXPECT_EQ(SSLPrivateKey::Type::ECDSA, wrapper_key->GetType()); + EXPECT_EQ(SSLPrivateKey::Type::ECDSA_P256, wrapper_key->GetType()); EXPECT_EQ(static_cast<size_t>(EVP_PKEY_size(openssl_key.get())), wrapper_key->GetMaxSignatureLengthInBytes());
diff --git a/net/ssl/ssl_platform_key_chromecast.cc b/net/ssl/ssl_platform_key_chromecast.cc index a800d057..429703d 100644 --- a/net/ssl/ssl_platform_key_chromecast.cc +++ b/net/ssl/ssl_platform_key_chromecast.cc
@@ -17,7 +17,7 @@ #include "net/cert/x509_certificate.h" #include "net/ssl/client_key_store.h" #include "net/ssl/ssl_platform_key.h" -#include "net/ssl/ssl_platform_key_task_runner.h" +#include "net/ssl/ssl_platform_key_util.h" #include "net/ssl/ssl_private_key.h" #include "net/ssl/threaded_ssl_private_key.h"
diff --git a/net/ssl/ssl_platform_key_mac.cc b/net/ssl/ssl_platform_key_mac.cc index e7313c07..029c0f3 100644 --- a/net/ssl/ssl_platform_key_mac.cc +++ b/net/ssl/ssl_platform_key_mac.cc
@@ -29,7 +29,7 @@ #include "crypto/openssl_util.h" #include "net/base/net_errors.h" #include "net/cert/x509_certificate.h" -#include "net/ssl/ssl_platform_key_task_runner.h" +#include "net/ssl/ssl_platform_key_util.h" #include "net/ssl/ssl_private_key.h" #include "net/ssl/threaded_ssl_private_key.h" @@ -91,22 +91,18 @@ class SSLPlatformKeyMac : public ThreadedSSLPrivateKey::Delegate { public: - SSLPlatformKeyMac(SecKeyRef key, const CSSM_KEY* cssm_key) - : key_(key, base::scoped_policy::RETAIN), cssm_key_(cssm_key) { - DCHECK(cssm_key_->KeyHeader.AlgorithmId == CSSM_ALGID_RSA || - cssm_key_->KeyHeader.AlgorithmId == CSSM_ALGID_ECDSA); - } + SSLPlatformKeyMac(SSLPrivateKey::Type type, + size_t max_length, + SecKeyRef key, + const CSSM_KEY* cssm_key) + : type_(type), + max_length_(max_length), + key_(key, base::scoped_policy::RETAIN), + cssm_key_(cssm_key) {} ~SSLPlatformKeyMac() override {} - SSLPrivateKey::Type GetType() override { - if (cssm_key_->KeyHeader.AlgorithmId == CSSM_ALGID_RSA) { - return SSLPrivateKey::Type::RSA; - } else { - DCHECK_EQ(CSSM_ALGID_ECDSA, cssm_key_->KeyHeader.AlgorithmId); - return SSLPrivateKey::Type::ECDSA; - } - } + SSLPrivateKey::Type GetType() override { return type_; } std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override { static const SSLPrivateKey::Hash kHashes[] = { @@ -116,17 +112,7 @@ kHashes + arraysize(kHashes)); } - size_t GetMaxSignatureLengthInBytes() override { - if (cssm_key_->KeyHeader.AlgorithmId == CSSM_ALGID_RSA) { - return (cssm_key_->KeyHeader.LogicalKeySizeInBits + 7) / 8; - } else { - // LogicalKeySizeInBits is the size of an EC public key. But an - // ECDSA signature length depends on the size of the base point's - // order. For P-256, P-384, and P-521, these two sizes are the same. - return ECDSA_SIG_max_len((cssm_key_->KeyHeader.LogicalKeySizeInBits + 7) / - 8); - } - } + size_t GetMaxSignatureLengthInBytes() override { return max_length_; } Error SignDigest(SSLPrivateKey::Hash hash, const base::StringPiece& input, @@ -202,7 +188,7 @@ } } - signature->resize(GetMaxSignatureLengthInBytes()); + signature->resize(max_length_); CSSM_DATA signature_data; signature_data.Length = signature->size(); signature_data.Data = signature->data(); @@ -216,6 +202,8 @@ } private: + SSLPrivateKey::Type type_; + size_t max_length_; base::ScopedCFTypeRef<SecKeyRef> key_; const CSSM_KEY* cssm_key_; @@ -237,13 +225,14 @@ if (status != noErr) return nullptr; - if (cssm_key->KeyHeader.AlgorithmId != CSSM_ALGID_RSA && - cssm_key->KeyHeader.AlgorithmId != CSSM_ALGID_ECDSA) { - LOG(ERROR) << "Unknown key type: " << cssm_key->KeyHeader.AlgorithmId; + SSLPrivateKey::Type key_type; + size_t max_length; + if (!GetClientCertInfo(certificate, &key_type, &max_length)) return nullptr; - } + return make_scoped_refptr(new ThreadedSSLPrivateKey( - base::MakeUnique<SSLPlatformKeyMac>(private_key.get(), cssm_key), + base::MakeUnique<SSLPlatformKeyMac>(key_type, max_length, + private_key.get(), cssm_key), GetSSLPlatformKeyTaskRunner())); }
diff --git a/net/ssl/ssl_platform_key_nss.cc b/net/ssl/ssl_platform_key_nss.cc index e5712940..687f7962 100644 --- a/net/ssl/ssl_platform_key_nss.cc +++ b/net/ssl/ssl_platform_key_nss.cc
@@ -2,8 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <cert.h> #include <keyhi.h> #include <openssl/bn.h> +#include <openssl/bytestring.h> +#include <openssl/ec.h> +#include <openssl/ec_key.h> #include <openssl/ecdsa.h> #include <openssl/mem.h> #include <openssl/nid.h> @@ -21,7 +25,7 @@ #include "net/cert/x509_certificate.h" #include "net/ssl/client_key_store.h" #include "net/ssl/ssl_platform_key.h" -#include "net/ssl/ssl_platform_key_task_runner.h" +#include "net/ssl/ssl_platform_key_util.h" #include "net/ssl/ssl_private_key.h" #include "net/ssl/threaded_ssl_private_key.h" @@ -29,19 +33,20 @@ namespace { -void LogPRError() { +void LogPRError(const char* message) { PRErrorCode err = PR_GetError(); const char* err_name = PR_ErrorToName(err); if (err_name == nullptr) err_name = ""; - LOG(ERROR) << "Could not sign digest: " << err << " (" << err_name << ")"; + LOG(ERROR) << message << ": " << err << " (" << err_name << ")"; } class SSLPlatformKeyNSS : public ThreadedSSLPrivateKey::Delegate { public: SSLPlatformKeyNSS(SSLPrivateKey::Type type, + size_t max_length, crypto::ScopedSECKEYPrivateKey key) - : type_(type), key_(std::move(key)) {} + : type_(type), max_length_(max_length), key_(std::move(key)) {} ~SSLPlatformKeyNSS() override {} SSLPrivateKey::Type GetType() override { return type_; } @@ -54,15 +59,7 @@ kHashes + arraysize(kHashes)); } - size_t GetMaxSignatureLengthInBytes() override { - int len = PK11_SignatureLen(key_.get()); - if (len <= 0) - return 0; - // NSS signs raw ECDSA signatures rather than a DER-encoded ECDSA-Sig-Value. - if (type_ == SSLPrivateKey::Type::ECDSA) - return ECDSA_SIG_max_len(static_cast<size_t>(len) / 2); - return static_cast<size_t>(len); - } + size_t GetMaxSignatureLengthInBytes() override { return max_length_; } Error SignDigest(SSLPrivateKey::Hash hash, const base::StringPiece& input, @@ -107,7 +104,7 @@ int len = PK11_SignatureLen(key_.get()); if (len <= 0) { - LogPRError(); + LogPRError("PK11_SignatureLen failed"); return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; } signature->resize(len); @@ -117,14 +114,14 @@ SECStatus rv = PK11_Sign(key_.get(), &signature_item, &digest_item); if (rv != SECSuccess) { - LogPRError(); + LogPRError("PK11_Sign failed"); return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; } signature->resize(signature_item.len); // NSS emits raw ECDSA signatures, but BoringSSL expects a DER-encoded // ECDSA-Sig-Value. - if (type_ == SSLPrivateKey::Type::ECDSA) { + if (SSLPrivateKey::IsECDSAType(type_)) { if (signature->size() % 2 != 0) { LOG(ERROR) << "Bad signature length"; return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; @@ -154,6 +151,7 @@ private: SSLPrivateKey::Type type_; + size_t max_length_; crypto::ScopedSECKEYPrivateKey key_; DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyNSS); @@ -170,21 +168,13 @@ *certificate); } - KeyType nss_type = SECKEY_GetPrivateKeyType(key.get()); SSLPrivateKey::Type type; - switch (nss_type) { - case rsaKey: - type = SSLPrivateKey::Type::RSA; - break; - case ecKey: - type = SSLPrivateKey::Type::ECDSA; - break; - default: - LOG(ERROR) << "Unknown key type: " << nss_type; - return nullptr; - } + size_t max_length; + if (!GetClientCertInfo(certificate, &type, &max_length)) + return nullptr; + return make_scoped_refptr(new ThreadedSSLPrivateKey( - base::MakeUnique<SSLPlatformKeyNSS>(type, std::move(key)), + base::MakeUnique<SSLPlatformKeyNSS>(type, max_length, std::move(key)), GetSSLPlatformKeyTaskRunner())); }
diff --git a/net/ssl/ssl_platform_key_task_runner.cc b/net/ssl/ssl_platform_key_task_runner.cc deleted file mode 100644 index 2ef8469..0000000 --- a/net/ssl/ssl_platform_key_task_runner.cc +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/ssl/ssl_platform_key_task_runner.h" - -#include "base/lazy_instance.h" - -namespace net { - -SSLPlatformKeyTaskRunner::SSLPlatformKeyTaskRunner() - : worker_thread_("Platform Key Thread") { - base::Thread::Options options; - options.joinable = false; - worker_thread_.StartWithOptions(options); -} - -SSLPlatformKeyTaskRunner::~SSLPlatformKeyTaskRunner() = default; - -scoped_refptr<base::SingleThreadTaskRunner> -SSLPlatformKeyTaskRunner::task_runner() { - return worker_thread_.task_runner(); -} - -base::LazyInstance<SSLPlatformKeyTaskRunner>::Leaky g_platform_key_task_runner = - LAZY_INSTANCE_INITIALIZER; - -scoped_refptr<base::SingleThreadTaskRunner> GetSSLPlatformKeyTaskRunner() { - return g_platform_key_task_runner.Get().task_runner(); -} - -} // namespace net
diff --git a/net/ssl/ssl_platform_key_task_runner.h b/net/ssl/ssl_platform_key_task_runner.h deleted file mode 100644 index cb6b4b4c..0000000 --- a/net/ssl/ssl_platform_key_task_runner.h +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_SSL_SSL_PLATFORM_KEY_TASK_RUNNER_H_ -#define NET_SSL_SSL_PLATFORM_KEY_TASK_RUNNER_H_ - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/threading/thread.h" - -namespace base { -class SingleThreadTaskRunner; -} - -namespace net { - -// Serialize all the private key operations on a single background thread to -// avoid problems with buggy smartcards. Its underlying Thread is non-joinable -// and as such provides TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN semantics. -class SSLPlatformKeyTaskRunner { - public: - SSLPlatformKeyTaskRunner(); - ~SSLPlatformKeyTaskRunner(); - - scoped_refptr<base::SingleThreadTaskRunner> task_runner(); - - private: - base::Thread worker_thread_; - - DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyTaskRunner); -}; - -scoped_refptr<base::SingleThreadTaskRunner> GetSSLPlatformKeyTaskRunner(); - -} // namespace net - -#endif // NET_SSL_SSL_PLATFORM_KEY_TASK_RUNNER_H_
diff --git a/net/ssl/ssl_platform_key_util.cc b/net/ssl/ssl_platform_key_util.cc new file mode 100644 index 0000000..11d8334 --- /dev/null +++ b/net/ssl/ssl_platform_key_util.cc
@@ -0,0 +1,107 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/ssl/ssl_platform_key_util.h" + +#include <openssl/bytestring.h> +#include <openssl/ec_key.h> +#include <openssl/evp.h> + +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/strings/string_piece.h" +#include "base/threading/thread.h" +#include "crypto/openssl_util.h" +#include "net/cert/asn1_util.h" +#include "net/cert/x509_certificate.h" + +namespace net { + +namespace { + +class SSLPlatformKeyTaskRunner { + public: + SSLPlatformKeyTaskRunner() : worker_thread_("Platform Key Thread") { + base::Thread::Options options; + options.joinable = false; + worker_thread_.StartWithOptions(options); + } + + ~SSLPlatformKeyTaskRunner() {} + + scoped_refptr<base::SingleThreadTaskRunner> task_runner() { + return worker_thread_.task_runner(); + } + + private: + base::Thread worker_thread_; + + DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyTaskRunner); +}; + +base::LazyInstance<SSLPlatformKeyTaskRunner>::Leaky g_platform_key_task_runner = + LAZY_INSTANCE_INITIALIZER; + +} // namespace + +scoped_refptr<base::SingleThreadTaskRunner> GetSSLPlatformKeyTaskRunner() { + return g_platform_key_task_runner.Get().task_runner(); +} + +bool GetClientCertInfo(const X509Certificate* certificate, + SSLPrivateKey::Type* out_type, + size_t* out_max_length) { + crypto::OpenSSLErrStackTracer tracker(FROM_HERE); + + std::string der_encoded; + base::StringPiece spki; + if (!X509Certificate::GetDEREncoded(certificate->os_cert_handle(), + &der_encoded) || + !asn1::ExtractSPKIFromDERCert(der_encoded, &spki)) { + LOG(ERROR) << "Could not extract SPKI from certificate."; + return false; + } + + CBS cbs; + CBS_init(&cbs, reinterpret_cast<const uint8_t*>(spki.data()), spki.size()); + bssl::UniquePtr<EVP_PKEY> key(EVP_parse_public_key(&cbs)); + if (!key || CBS_len(&cbs) != 0) { + LOG(ERROR) << "Could not parse public key."; + return false; + } + + switch (EVP_PKEY_id(key.get())) { + case EVP_PKEY_RSA: + *out_type = SSLPrivateKey::Type::RSA; + break; + + case EVP_PKEY_EC: { + EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key.get()); + int curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)); + switch (curve) { + case NID_X9_62_prime256v1: + *out_type = SSLPrivateKey::Type::ECDSA_P256; + break; + case NID_secp384r1: + *out_type = SSLPrivateKey::Type::ECDSA_P384; + break; + case NID_secp521r1: + *out_type = SSLPrivateKey::Type::ECDSA_P384; + break; + default: + return false; + } + break; + } + + default: + return false; + } + + *out_max_length = EVP_PKEY_size(key.get()); + return true; +} + +} // namespace net
diff --git a/net/ssl/ssl_platform_key_util.h b/net/ssl/ssl_platform_key_util.h new file mode 100644 index 0000000..5fda648 --- /dev/null +++ b/net/ssl/ssl_platform_key_util.h
@@ -0,0 +1,36 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_SSL_SSL_PLATFORM_KEY_UTIL_H_ +#define NET_SSL_SSL_PLATFORM_KEY_UTIL_H_ + +#include <stddef.h> + +#include "base/memory/ref_counted.h" +#include "net/base/net_export.h" +#include "net/ssl/ssl_private_key.h" + +namespace base { +class SingleThreadTaskRunner; +} + +namespace net { + +class X509Certificate; + +// Returns a task runner to serialize all private key operations on a single +// background thread to avoid problems with buggy smartcards. Its underlying +// Thread is non-joinable and as such provides +// TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN semantics. +scoped_refptr<base::SingleThreadTaskRunner> GetSSLPlatformKeyTaskRunner(); + +// Determines the key type and maximum signature length of |certificate|'s +// public key. +NET_EXPORT_PRIVATE bool GetClientCertInfo(const X509Certificate* certificate, + SSLPrivateKey::Type* out_type, + size_t* out_max_length); + +} // namespace net + +#endif // NET_SSL_SSL_PLATFORM_KEY_UTIL_H_
diff --git a/net/ssl/ssl_platform_key_util_unittest.cc b/net/ssl/ssl_platform_key_util_unittest.cc new file mode 100644 index 0000000..c7e9130 --- /dev/null +++ b/net/ssl/ssl_platform_key_util_unittest.cc
@@ -0,0 +1,49 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/ssl/ssl_platform_key_util.h" + +#include <openssl/ecdsa.h> +#include <stddef.h> + +#include "base/memory/ref_counted.h" +#include "net/cert/x509_certificate.h" +#include "net/ssl/ssl_private_key.h" +#include "net/test/cert_test_util.h" +#include "net/test/test_data_directory.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +namespace { + +bool GetClientCertInfoFromFile(const char* filename, + SSLPrivateKey::Type* out_type, + size_t* out_max_length) { + scoped_refptr<X509Certificate> cert = + ImportCertFromFile(GetTestCertsDirectory(), filename); + if (!cert) { + ADD_FAILURE() << "Could not read " << filename; + return false; + } + + return GetClientCertInfo(cert.get(), out_type, out_max_length); +} + +} // namespace + +TEST(SSLPlatformKeyUtil, GetClientCertInfo) { + SSLPrivateKey::Type type; + size_t max_length; + + ASSERT_TRUE(GetClientCertInfoFromFile("client_1.pem", &type, &max_length)); + EXPECT_EQ(SSLPrivateKey::Type::RSA, type); + EXPECT_EQ(2048u / 8u, max_length); + + ASSERT_TRUE(GetClientCertInfoFromFile("client_4.pem", &type, &max_length)); + EXPECT_EQ(SSLPrivateKey::Type::ECDSA_P256, type); + EXPECT_EQ(ECDSA_SIG_max_len(256u / 8u), max_length); +} + +} // namespace net
diff --git a/net/ssl/ssl_platform_key_win.cc b/net/ssl/ssl_platform_key_win.cc index e1dbd576..40913aa 100644 --- a/net/ssl/ssl_platform_key_win.cc +++ b/net/ssl/ssl_platform_key_win.cc
@@ -25,7 +25,7 @@ #include "crypto/wincrypt_shim.h" #include "net/base/net_errors.h" #include "net/cert/x509_certificate.h" -#include "net/ssl/ssl_platform_key_task_runner.h" +#include "net/ssl/ssl_platform_key_util.h" #include "net/ssl/ssl_private_key.h" #include "net/ssl/threaded_ssl_private_key.h" @@ -211,7 +211,7 @@ // CNG emits raw ECDSA signatures, but BoringSSL expects a DER-encoded // ECDSA-Sig-Value. - if (type_ == SSLPrivateKey::Type::ECDSA) { + if (SSLPrivateKey::IsECDSAType(type_)) { if (signature->size() % 2 != 0) { LOG(ERROR) << "Bad signature length"; return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; @@ -247,38 +247,6 @@ DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyCNG); }; -// Determines the key type and maximum signature length of |certificate|'s -// public key. -bool GetKeyInfo(const X509Certificate* certificate, - SSLPrivateKey::Type* out_type, - size_t* out_max_length) { - crypto::OpenSSLErrStackTracer tracker(FROM_HERE); - - std::string der_encoded; - if (!X509Certificate::GetDEREncoded(certificate->os_cert_handle(), - &der_encoded)) - return false; - const uint8_t* bytes = reinterpret_cast<const uint8_t*>(der_encoded.data()); - bssl::UniquePtr<X509> x509(d2i_X509(nullptr, &bytes, der_encoded.size())); - if (!x509) - return false; - bssl::UniquePtr<EVP_PKEY> key(X509_get_pubkey(x509.get())); - if (!key) - return false; - switch (EVP_PKEY_id(key.get())) { - case EVP_PKEY_RSA: - *out_type = SSLPrivateKey::Type::RSA; - break; - case EVP_PKEY_EC: - *out_type = SSLPrivateKey::Type::ECDSA; - break; - default: - return false; - } - *out_max_length = EVP_PKEY_size(key.get()); - return true; -} - } // namespace scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey( @@ -288,7 +256,7 @@ // consistently work depending on the system. See https://crbug.com/468345. SSLPrivateKey::Type key_type; size_t max_length; - if (!GetKeyInfo(certificate, &key_type, &max_length)) + if (!GetClientCertInfo(certificate, &key_type, &max_length)) return nullptr; PCCERT_CONTEXT cert_context = certificate->os_cert_handle();
diff --git a/net/ssl/ssl_private_key.h b/net/ssl/ssl_private_key.h index 2e382fb..145cd503 100644 --- a/net/ssl/ssl_private_key.h +++ b/net/ssl/ssl_private_key.h
@@ -25,9 +25,17 @@ enum class Type { RSA, - ECDSA, + ECDSA_P256, + ECDSA_P384, + ECDSA_P521, }; + // Returns true if |type| is an ECDSA key type. + static bool IsECDSAType(Type type) { + return type == Type::ECDSA_P256 || type == Type::ECDSA_P384 || + type == Type::ECDSA_P521; + } + enum class Hash { MD5_SHA1, SHA1,
diff --git a/net/ssl/test_ssl_private_key.cc b/net/ssl/test_ssl_private_key.cc index ddcce88..59dea2f 100644 --- a/net/ssl/test_ssl_private_key.cc +++ b/net/ssl/test_ssl_private_key.cc
@@ -5,6 +5,7 @@ #include "net/ssl/test_ssl_private_key.h" #include <openssl/digest.h> +#include <openssl/ec.h> #include <openssl/evp.h> #include <openssl/rsa.h> @@ -14,7 +15,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "net/base/net_errors.h" -#include "net/ssl/ssl_platform_key_task_runner.h" +#include "net/ssl/ssl_platform_key_util.h" #include "net/ssl/ssl_private_key.h" #include "net/ssl/threaded_ssl_private_key.h" @@ -115,9 +116,25 @@ case EVP_PKEY_RSA: type = SSLPrivateKey::Type::RSA; break; - case EVP_PKEY_EC: - type = SSLPrivateKey::Type::ECDSA; + case EVP_PKEY_EC: { + EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key.get()); + int curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)); + switch (curve) { + case NID_X9_62_prime256v1: + type = SSLPrivateKey::Type::ECDSA_P256; + break; + case NID_secp384r1: + type = SSLPrivateKey::Type::ECDSA_P384; + break; + case NID_secp521r1: + type = SSLPrivateKey::Type::ECDSA_P384; + break; + default: + LOG(ERROR) << "Unknown curve: " << curve; + return nullptr; + } break; + } default: LOG(ERROR) << "Unknown key type: " << EVP_PKEY_id(key.get()); return nullptr;
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc index 2934efef..9201152 100644 --- a/net/tools/quic/end_to_end_test.cc +++ b/net/tools/quic/end_to_end_test.cc
@@ -1757,9 +1757,11 @@ QuicHeadersStream* headers_stream = QuicSpdySessionPeer::GetHeadersStream(client_->client()->session()); - EXPECT_LT( - QuicFlowControllerPeer::SendWindowSize(headers_stream->flow_controller()), - kStreamIFCW); + if (!client_->client()->session()->force_hol_blocking()) { + EXPECT_LT(QuicFlowControllerPeer::SendWindowSize( + headers_stream->flow_controller()), + kStreamIFCW); + } EXPECT_EQ(kSessionIFCW, QuicFlowControllerPeer::SendWindowSize( client_->client()->session()->flow_controller())); @@ -1799,12 +1801,14 @@ QuicSpdySessionPeer::GetHeadersStream(client_session)->flow_controller(), QuicSpdySessionPeer::GetHeadersStream(server_session)->flow_controller()); - EXPECT_EQ(static_cast<float>(QuicFlowControllerPeer::ReceiveWindowSize( - client_session->flow_controller())) / - QuicFlowControllerPeer::ReceiveWindowSize( - QuicSpdySessionPeer::GetHeadersStream(client_session) - ->flow_controller()), - kSessionToStreamRatio); + if (!client_session->force_hol_blocking()) { + EXPECT_EQ(static_cast<float>(QuicFlowControllerPeer::ReceiveWindowSize( + client_session->flow_controller())) / + QuicFlowControllerPeer::ReceiveWindowSize( + QuicSpdySessionPeer::GetHeadersStream(client_session) + ->flow_controller()), + kSessionToStreamRatio); + } server_thread_->Resume(); }
diff --git a/net/tools/quic/quic_simple_server_session.cc b/net/tools/quic/quic_simple_server_session.cc index 64d987b..a845e2c 100644 --- a/net/tools/quic/quic_simple_server_session.cc +++ b/net/tools/quic/quic_simple_server_session.cc
@@ -156,15 +156,15 @@ SpdyHeaderBlock spdy_headers = original_request_headers.Clone(); // :authority could be different from original request. - spdy_headers.ReplaceOrAppendHeader(":authority", push_request_url.host()); - spdy_headers.ReplaceOrAppendHeader(":path", path); + spdy_headers[":authority"] = push_request_url.host(); + spdy_headers[":path"] = path; // Push request always use GET. - spdy_headers.ReplaceOrAppendHeader(":method", "GET"); - spdy_headers.ReplaceOrAppendHeader("referer", request_url); - spdy_headers.ReplaceOrAppendHeader(":scheme", push_request_url.scheme()); + spdy_headers[":method"] = "GET"; + spdy_headers["referer"] = request_url; + spdy_headers[":scheme"] = push_request_url.scheme(); // It is not possible to push a response to a request that includes a request // body. - spdy_headers.ReplaceOrAppendHeader("content-length", "0"); + spdy_headers["content-length"] = "0"; // Remove "host" field as push request is a directly generated HTTP2 request // which should use ":authority" instead of "host". spdy_headers.erase("host");
diff --git a/net/tools/quic/spdy_balsa_utils.cc b/net/tools/quic/spdy_balsa_utils.cc index 509b3f61..b84e96fb 100644 --- a/net/tools/quic/spdy_balsa_utils.cc +++ b/net/tools/quic/spdy_balsa_utils.cc
@@ -62,7 +62,7 @@ for (const auto& header : header_values_map) { if (header.second.size() == 1) { // Avoid string allocation for the single value case. - block->ReplaceOrAppendHeader(header.first, header.second[0]); + (*block)[header.first] = header.second[0]; } else { StringPiece separator("\0", 1); auto it = header.second.begin(); @@ -72,7 +72,7 @@ separator.AppendToString(&value); value.append(it->data(), it->size()); } - block->ReplaceOrAppendHeader(header.first, value); + (*block)[header.first] = value; } } }
diff --git a/net/tools/stress_cache/stress_cache.cc b/net/tools/stress_cache/stress_cache.cc index b4375f4..fefcd72f 100644 --- a/net/tools/stress_cache/stress_cache.cc +++ b/net/tools/stress_cache/stress_cache.cc
@@ -341,11 +341,11 @@ bool g_crashing = false; // RunSoon() and CrashCallback() reference each other, unfortunately. -void RunSoon(base::MessageLoop* target_loop); +void RunSoon(scoped_refptr<base::SingleThreadTaskRunner> task_runner); void CrashCallback() { // Keep trying to run. - RunSoon(base::MessageLoop::current()); + RunSoon(base::ThreadTaskRunnerHandle::Get()); if (g_crashing) return; @@ -363,10 +363,10 @@ } } -void RunSoon(base::MessageLoop* target_loop) { +void RunSoon(scoped_refptr<base::SingleThreadTaskRunner> task_runner) { const base::TimeDelta kTaskDelay = base::TimeDelta::FromSeconds(10); - target_loop->task_runner()->PostDelayedTask( - FROM_HERE, base::Bind(&CrashCallback), kTaskDelay); + task_runner->PostDelayedTask(FROM_HERE, base::Bind(&CrashCallback), + kTaskDelay); } // We leak everything here :) @@ -375,7 +375,7 @@ if (!thread->Start()) return false; - RunSoon(thread->message_loop()); + RunSoon(thread->task_runner()); return true; }
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index 26c3ac9..61308fa 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc
@@ -12,12 +12,12 @@ #include "base/compiler_specific.h" #include "base/lazy_instance.h" #include "base/memory/singleton.h" -#include "base/message_loop/message_loop.h" #include "base/profiler/scoped_tracker.h" #include "base/rand_util.h" #include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" #include "base/synchronization/lock.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "net/base/auth.h" #include "net/base/host_port_pair.h" @@ -578,8 +578,7 @@ received_response_content_length_(0), creation_time_(base::TimeTicks::Now()) { // Sanity check out environment. - DCHECK(base::MessageLoop::current()) - << "The current base::MessageLoop must exist"; + DCHECK(base::ThreadTaskRunnerHandle::IsSet()); context->url_requests()->insert(this); net_log_.BeginEvent(NetLogEventType::REQUEST_ALIVE);
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc index e6b3bdf..dcfdeaa 100644 --- a/net/url_request/url_request_job.cc +++ b/net/url_request/url_request_job.cc
@@ -611,24 +611,6 @@ request_->set_status(status); } - // If the request succeeded (And wasn't cancelled) and the response code was - // 4xx or 5xx, record whether or not the main frame was blank. This is - // intended to be a short-lived histogram, used to figure out how important - // fixing http://crbug.com/331745 is. - if (request_->status().is_success()) { - int response_code = GetResponseCode(); - if (400 <= response_code && response_code <= 599) { - bool page_has_content = (postfilter_bytes_read_ != 0); - if (request_->load_flags() & net::LOAD_MAIN_FRAME_DEPRECATED) { - UMA_HISTOGRAM_BOOLEAN("Net.ErrorResponseHasContentMainFrame", - page_has_content); - } else { - UMA_HISTOGRAM_BOOLEAN("Net.ErrorResponseHasContentNonMainFrame", - page_has_content); - } - } - } - MaybeNotifyNetworkBytes(); // Complete this notification later. This prevents us from re-entering the
diff --git a/remoting/android/java/src/org/chromium/chromoting/Chromoting.java b/remoting/android/java/src/org/chromium/chromoting/Chromoting.java index a14c20b..1d5f1c0 100644 --- a/remoting/android/java/src/org/chromium/chromoting/Chromoting.java +++ b/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
@@ -244,8 +244,7 @@ findViewById(R.id.host_setup_link_android).setOnClickListener(this); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); - mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, - R.string.open_navigation_drawer, R.string.close_navigation_drawer) { + mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, 0, 0) { @Override public void onDrawerClosed(View drawerView) { super.onDrawerClosed(drawerView); @@ -287,6 +286,7 @@ DrawableCompat.setTint(menuIcon.mutate(), ChromotingUtil.getColorAttribute(this, R.attr.colorControlNormal)); getSupportActionBar().setHomeAsUpIndicator(menuIcon); + getSupportActionBar().setHomeActionContentDescription(R.string.actionbar_menu); mAccountSwitcher = AccountSwitcherFactory.getInstance().createAccountSwitcher(this, this); mAccountSwitcher.setNavigation(NavigationMenuAdapter.createNavigationMenu(this));
diff --git a/remoting/base/BUILD.gn b/remoting/base/BUILD.gn index 194777b..c8f5a2d 100644 --- a/remoting/base/BUILD.gn +++ b/remoting/base/BUILD.gn
@@ -43,7 +43,10 @@ "vlog_net_log.h", ] - configs += [ "//build/config/compiler:wexit_time_destructors" ] + configs += [ + "//build/config/compiler:wexit_time_destructors", + "//remoting/build/config:version", + ] public_deps = [ "//base",
diff --git a/remoting/base/chromoting_event.cc b/remoting/base/chromoting_event.cc index e7a02eb8..51f725d 100644 --- a/remoting/base/chromoting_event.cc +++ b/remoting/base/chromoting_event.cc
@@ -4,6 +4,7 @@ #include "remoting/base/chromoting_event.h" +#include "base/strings/stringize_macros.h" #include "base/sys_info.h" namespace remoting { @@ -29,6 +30,7 @@ const char ChromotingEvent::kSessionStateKey[] = "session_state"; const char ChromotingEvent::kTypeKey[] = "type"; const char ChromotingEvent::kVideoBandwidthKey[] = "video_bandwidth"; +const char ChromotingEvent::kWebAppVersionKey[] = "webapp_version"; ChromotingEvent::ChromotingEvent() : values_map_(new base::DictionaryValue()) {} @@ -82,7 +84,7 @@ void ChromotingEvent::AddSystemInfo() { SetString(kCpuKey, base::SysInfo::OperatingSystemArchitecture()); SetString(kOsVersionKey, base::SysInfo::OperatingSystemVersion()); - std::string osName = base::SysInfo::OperatingSystemName(); + SetString(kWebAppVersionKey, STRINGIZE(VERSION)); #if defined(OS_LINUX) Os os = Os::CHROMOTING_LINUX; #elif defined(OS_CHROMEOS)
diff --git a/remoting/base/chromoting_event.h b/remoting/base/chromoting_event.h index b8527a42..3e7a959 100644 --- a/remoting/base/chromoting_event.h +++ b/remoting/base/chromoting_event.h
@@ -108,6 +108,7 @@ static const char kSessionStateKey[]; static const char kTypeKey[]; static const char kVideoBandwidthKey[]; + static const char kWebAppVersionKey[]; ChromotingEvent(); explicit ChromotingEvent(Type type);
diff --git a/remoting/host/installer/win/BUILD.gn b/remoting/host/installer/win/BUILD.gn index 372ff37..08908831 100644 --- a/remoting/host/installer/win/BUILD.gn +++ b/remoting/host/installer/win/BUILD.gn
@@ -140,5 +140,9 @@ } } else { group("remoting_host_installation") { + # We still want to build host archive under other configurations. + deps = [ + "//remoting/host:remoting_me2me_host_archive", + ] } }
diff --git a/remoting/resources/remoting_strings.grd b/remoting/resources/remoting_strings.grd index dad968a..cb92e80 100644 --- a/remoting/resources/remoting_strings.grd +++ b/remoting/resources/remoting_strings.grd
@@ -616,12 +616,6 @@ <message desc="Title for Cast button in Android application menu." name="IDS_CAST_BUTTON_TITLE" formatter_data="android_java"> Cast </message> - <message desc="Text for the Android action-bar button which opens the sliding navigation drawer when touched." name="IDS_OPEN_NAVIGATION_DRAWER" formatter_data="android_java"> - Open navigation drawer - </message> - <message desc="Text for the Android action-bar button which closes the sliding navigation drawer when touched." name="IDS_CLOSE_NAVIGATION_DRAWER" formatter_data="android_java"> - Close navigation drawer - </message> <!-- Play Store listings text. These Android-specific strings are not marked with formatter_data="android_java" since they are used only for the Play @@ -1160,6 +1154,9 @@ <message desc="Label for the Feedback button displayed in the Android Help screen. Pressing this button causes the Feedback screen to be shown." name="IDS_ACTIONBAR_FEEDBACK" formatter_data="android_java"> Feedback </message> + <message desc="Label for the menu button displayed on the Android toolbar. Pressing this button will open a drawer with a list of menu options." name="IDS_ACTIONBAR_MENU" formatter_data="android_java"> + Menu + </message> <message desc="Label for button to accept remote assistance. This button appears in the Hangouts confirm dialog." name="IDS_HANGOUTS_CONFIRM_DIALOG_ACCEPT" > Accept </message>
diff --git a/storage/browser/fileapi/plugin_private_file_system_backend.cc b/storage/browser/fileapi/plugin_private_file_system_backend.cc index 06e9aef..efb51f7 100644 --- a/storage/browser/fileapi/plugin_private_file_system_backend.cc +++ b/storage/browser/fileapi/plugin_private_file_system_backend.cc
@@ -10,6 +10,8 @@ #include <memory> #include <utility> +#include "base/files/file_enumerator.h" +#include "base/files/file_path.h" #include "base/stl_util.h" #include "base/synchronization/lock.h" #include "base/task_runner_util.h" @@ -266,8 +268,75 @@ FileSystemContext* context, const GURL& origin_url, FileSystemType type) { - // We don't track usage on this filesystem. - return 0; + DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); + + if (!CanHandleType(type)) + return 0; + + int64_t total_size; + base::Time last_modified_time; + GetOriginDetailsOnFileTaskRunner(context, origin_url, &total_size, + &last_modified_time); + return total_size; +} + +void PluginPrivateFileSystemBackend::GetOriginDetailsOnFileTaskRunner( + FileSystemContext* context, + const GURL& origin_url, + int64_t* total_size, + base::Time* last_modified_time) { + DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); + + *total_size = 0; + *last_modified_time = base::Time::UnixEpoch(); + std::string fsid = + storage::IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath( + storage::kFileSystemTypePluginPrivate, "pluginprivate", + base::FilePath()); + DCHECK(storage::ValidateIsolatedFileSystemId(fsid)); + + std::string root = storage::GetIsolatedFileSystemRootURIString( + origin_url, fsid, "pluginprivate"); + + std::unique_ptr<FileSystemOperationContext> operation_context( + new FileSystemOperationContext(context)); + + // Determine the available plugin private filesystem directories for this + // origin. Currently the plugin private filesystem is only used by Encrypted + // Media Content Decryption Modules. Each CDM gets a directory based on the + // mimetype (e.g. plugin application/x-ppapi-widevine-cdm uses directory + // application_x-ppapi-widevine-cdm). Enumerate through the set of + // directories so that data from any CDM used by this origin is counted. + base::File::Error error; + base::FilePath path = obfuscated_file_util()->GetDirectoryForOriginAndType( + origin_url, "", false, &error); + if (error != base::File::FILE_OK) { + DLOG(ERROR) << "Unable to read directory for " << origin_url; + return; + } + + base::FileEnumerator directory_enumerator(path, false, + base::FileEnumerator::DIRECTORIES); + base::FilePath plugin_path; + while (!(plugin_path = directory_enumerator.Next()).empty()) { + std::string plugin_name = plugin_path.BaseName().MaybeAsASCII(); + if (OpenFileSystemOnFileTaskRunner( + obfuscated_file_util(), plugin_map_, origin_url, fsid, plugin_name, + storage::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT) != + base::File::FILE_OK) { + continue; + } + + std::unique_ptr<FileSystemFileUtil::AbstractFileEnumerator> enumerator( + obfuscated_file_util()->CreateFileEnumerator( + operation_context.get(), context->CrackURL(GURL(root)), true)); + + while (!enumerator->Next().empty()) { + *total_size += enumerator->Size(); + if (enumerator->LastModifiedTime() > *last_modified_time) + *last_modified_time = enumerator->LastModifiedTime(); + } + } } scoped_refptr<QuotaReservation>
diff --git a/storage/browser/fileapi/plugin_private_file_system_backend.h b/storage/browser/fileapi/plugin_private_file_system_backend.h index 95ffb64..89da39bf 100644 --- a/storage/browser/fileapi/plugin_private_file_system_backend.h +++ b/storage/browser/fileapi/plugin_private_file_system_backend.h
@@ -118,6 +118,15 @@ const GURL& origin_url, FileSystemType type) override; + // Get details on the files saved for the specified |origin_url|. Returns + // the total size and last modified time for the set of all files stored + // for the particular origin. |total_size| = 0 and |last_modified_time| = + // base::Time::UnixEpoch() if no files found. + void GetOriginDetailsOnFileTaskRunner(FileSystemContext* context, + const GURL& origin_url, + int64_t* total_size, + base::Time* last_modified_time); + private: friend class content::PluginPrivateFileSystemBackendTest;
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index 47ba91e..792fa878 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -2824,984 +2824,106 @@ "Lollipop Phone Tester": { "gtest_tests": [ { - "override_isolate_target": "android_webview_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "android_webview_unittests" }, { - "override_isolate_target": "base_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "base_unittests" }, { - "override_isolate_target": "blimp_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "blimp_unittests" }, { "override_compile_targets": [ "breakpad_unittests_deps" ], - "override_isolate_target": "breakpad_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "breakpad_unittests" }, { - "override_isolate_target": "capture_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "capture_unittests" }, { - "override_isolate_target": "cc_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "cc_unittests" }, { - "override_isolate_target": "components_browsertests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "components_browsertests" }, { - "override_isolate_target": "components_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "components_unittests" }, { - "override_isolate_target": "content_browsertests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "content_browsertests" }, { - "override_isolate_target": "content_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "content_unittests" }, { - "override_isolate_target": "device_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "device_unittests" }, { - "override_isolate_target": "events_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "events_unittests" }, { - "override_isolate_target": "gl_tests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "gl_tests" }, { - "override_isolate_target": "gl_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "gl_unittests" }, { - "override_isolate_target": "gpu_ipc_service_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "gpu_ipc_service_unittests" }, { - "override_isolate_target": "gpu_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "gpu_unittests" }, { - "override_isolate_target": "ipc_tests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "ipc_tests" }, { - "override_isolate_target": "media_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "media_unittests" }, { - "override_isolate_target": "net_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "net_unittests" }, { "override_compile_targets": [ "sandbox_linux_unittests_deps" ], - "override_isolate_target": "sandbox_linux_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "sandbox_linux_unittests" }, { - "override_isolate_target": "sql_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "sql_unittests" }, { - "override_isolate_target": "ui_android_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "ui_android_unittests" }, { - "override_isolate_target": "ui_base_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "ui_base_unittests" }, { - "override_isolate_target": "ui_touch_selection_unittests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "ui_touch_selection_unittests" }, { - "override_isolate_target": "unit_tests", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "unit_tests" - }, + } + ], + "instrumentation_tests": [ { - "override_compile_targets": [ - "android_webview_test_apk" - ], - "override_isolate_target": "android_webview_test_apk", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "android_webview_test_apk" }, { + "apk_under_test": "Blimp.apk", "override_compile_targets": [ "blimp_test_apk" ], - "override_isolate_target": "blimp_test_apk", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, - "test": "blimp_test_apk" + "test": "blimp_test_apk", + "test_apk": "BlimpTest.apk" }, { - "override_compile_targets": [ - "chrome_public_test_apk" - ], - "override_isolate_target": "chrome_public_test_apk", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "chrome_public_test_apk" }, { - "override_compile_targets": [ - "chrome_sync_shell_test_apk" - ], - "override_isolate_target": "chrome_sync_shell_test_apk", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "chrome_sync_shell_test_apk" }, { - "override_compile_targets": [ - "content_shell_test_apk" - ], - "override_isolate_target": "content_shell_test_apk", - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a" - } - ], - "dimension_sets": [ - { - "android_devices": "4", - "device_os": "LMY48I", - "device_type": "hammerhead" - } - ], - "hard_timeout": 960, - "output_links": [ - { - "link": [ - "https://luci-logdog.appspot.com/v/?s", - "=android%2Fswarming%2Flogcats%2F", - "${TASK_ID}%2F%2B%2Funified_logcats" - ], - "name": "shard #${SHARD_INDEX} logcats" - } - ] - }, "test": "content_shell_test_apk" } ]
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 542c94bc..eb8b0fab 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -11300,6 +11300,37 @@ } ] }, + "Site Isolation Android": { + "gtest_tests": [ + { + "override_isolate_target": "content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "4", + "device_type": "bullhead" + } + ], + "hard_timeout": 960 + }, + "test": "content_browsertests" + }, + { + "override_isolate_target": "content_unittests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "android_devices": "4", + "device_type": "bullhead" + } + ] + }, + "test": "content_unittests" + } + ] + }, "Site Isolation Linux": { "gtest_tests": [ {
diff --git a/testing/buildbot/filters/browser-side-navigation.linux.browser_tests.filter b/testing/buildbot/filters/browser-side-navigation.linux.browser_tests.filter index bf33a295..82fe116d 100644 --- a/testing/buildbot/filters/browser-side-navigation.linux.browser_tests.filter +++ b/testing/buildbot/filters/browser-side-navigation.linux.browser_tests.filter
@@ -58,22 +58,15 @@ -WebNavigationApiTest.RequestOpenTab -WebNavigationApiTest.SrcDoc -WebNavigationApiTest.UserAction --WebViewTests/WebViewPluginTest.TestLoadPluginInternalResource/0 --WebViewTests/WebViewPluginTest.TestLoadPluginInternalResource/1 -WebViewTests/WebViewTest.Shim_TestDeclarativeWebRequestAPI/* -WebViewTests/WebViewTest.Shim_TestDeclarativeWebRequestAPISendMessage/* -WebViewTests/WebViewTest.Shim_TestInlineScriptFromAccessibleResources/* --WebViewTests/WebViewTest.Shim_TestInvalidChromeExtensionURL/* --WebViewTests/WebViewTest.Shim_TestLoadAbortChromeExtensionURLWrongPartition/* --WebViewTests/WebViewTest.Shim_TestLoadAbortEmptyResponse/* --WebViewTests/WebViewTest.Shim_TestLoadStartLoadRedirect/* -WebViewTests/WebViewTest.Shim_TestMailtoLink/* -WebViewTests/WebViewTest.Shim_TestNavigationToExternalProtocol/* -WebViewTests/WebViewTest.Shim_TestNestedSubframes/* -WebViewTests/WebViewTest.Shim_TestWebRequestAPIErrorOccurred/* -WebViewTests/WebViewTest.Shim_TestWebRequestAPIGoogleProperty/* -WebViewTests/WebViewTest.Shim_TestWebRequestAPIWithHeaders/* --WebViewTests/WebViewTest.Shim_TestWebRequestListenerSurvivesReparenting/* -WebViewTests/WebViewTest.Shim_TestWebViewInsideFrame/* # Errors related to forms submission. @@ -81,7 +74,6 @@ -PhishingDOMFeatureExtractorTest.SubframeRemoval # https://crbug.com/647712: Nested URL blocking needs to work with PlzNavigate --ProcessManagerBrowserTest.NestedURLNavigationsToExtensionAllowed -ProcessManagerBrowserTest.NestedURLNavigationsToExtensionBlocked # Fail in Debug.
diff --git a/testing/buildbot/filters/site-per-process.browser_tests.filter b/testing/buildbot/filters/site-per-process.browser_tests.filter index fe2eeb3d..37980da 100644 --- a/testing/buildbot/filters/site-per-process.browser_tests.filter +++ b/testing/buildbot/filters/site-per-process.browser_tests.filter
@@ -1,34 +1,16 @@ # crbug.com/417518: Get tests working with --site-per-process --AllUrlsApiTest.WhitelistedExtension --BrowserNavigatorTest.NavigateFromNTPToOptionsInSameTab -BrowserTest.OtherRedirectsDontForkProcess -ChromeRenderProcessHostTest.ProcessOverflow -ChromeRenderProcessHostTest.ProcessPerTab -ChromeRenderProcessHostTestWithCommandLine.ProcessOverflowCommandLine --ErrorPageTest.DNSError_DoClickLink --ErrorPageTest.DNSError_DoReload --ErrorPageTest.DNSError_DoReloadAfterSamePageNavigation --PolicyTest.HomepageLocation -PrerenderBrowserTest.PrerenderLocationReplaceGWSHistograms -ProcessManagementTest.ExtensionProcessBalancing -ProcessManagementTest.ProcessOverflow -RedirectTest.ClientEmptyReferer -ReferrerPolicyTest.HttpsRedirect --RestoreOnStartupPolicyTestInstance/RestoreOnStartupPolicyTest.RunTest* -WebNavigationApiTest.ServerRedirectSingleProcess -# crbug.com/467126: BrowserTest.WindowOpenClose is flaky in --site-per-process -# mode: --BrowserTest.WindowOpenClose - -# crbug.com/483522 --ExtensionApiTest.Tabs2 - # crbug.com/448592: Get extension browsertests to pass with --site-per-process --ExtensionApiTest.TabMove --ExtensionApiTest.TabsOnUpdated --ExtensionURLRewriteBrowserTest.NewTabPageURL --InputImeApiTest.SendKeyEventsOnNormalPage -IsolatedAppTest.CookieIsolation -IsolatedAppTest.CrossProcessClientRedirect -IsolatedAppTest.IsolatedAppProcessModel
diff --git a/testing/buildbot/manage.py b/testing/buildbot/manage.py index 30612322..00b70ab 100755 --- a/testing/buildbot/manage.py +++ b/testing/buildbot/manage.py
@@ -126,6 +126,7 @@ # One off builders. Note that Swarming does support ARM. 'Linux ARM Cross-Compile', + 'Site Isolation Android', 'Site Isolation Linux', 'Site Isolation Win', }
diff --git a/testing/libfuzzer/getting_started.md b/testing/libfuzzer/getting_started.md index f8e55f7..1ccf2029 100644 --- a/testing/libfuzzer/getting_started.md +++ b/testing/libfuzzer/getting_started.md
@@ -16,7 +16,7 @@ ```bash # With address sanitizer -gn gen out/libfuzzer '--args=use_libfuzzer=true is_asan=true enable_nacl=false' --check +gn gen out/libfuzzer '--args=use_libfuzzer=true is_asan=true is_debug=false enable_nacl=false' --check ``` Supported sanitizer configurations are:
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=slimmingPaintInvalidation b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=slimmingPaintInvalidation index 60683bc..c9c1455 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=slimmingPaintInvalidation +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=slimmingPaintInvalidation
@@ -14,15 +14,16 @@ crbug.com/648769 paint/invalidation/transform-inline-layered-child.html [ Failure ] crbug.com/648769 paint/invalidation/transform-layout-repaint.html [ Failure ] crbug.com/648769 fast/sub-pixel/sub-pixel-accumulates-to-layers.html [ Failure ] -# This test is also affected by different clipping behavior. -crbug.com/648769 paint/invalidation/svg/animated-path-inside-transformed-html.xhtml [ Failure ] # We use FrameView::x() and FrameView::y() which are integers to generate FrameView # preTranslation, but the old path uses offsets in the layout tree. Not sure if it's # a bug of the new path or the old path. Bug(none) paint/invalidation/repaint-during-scroll-with-zoom.html [ Failure ] -# Missing SVG hairline stroke padding. -crbug.com/651511 paint/invalidation/svg/hairline-stroke-squarecap.svg [ Failure ] -crbug.com/651511 paint/invalidation/svg/tabgroup.svg [ Failure ] -crbug.com/651511 paint/invalidation/svg/window.svg [ Failure ] +# Missing SVG transform enclosingIntRect. +crbug.com/651521 paint/invalidation/svg/absolute-sized-document-no-scrollbars.svg [ Failure ] +crbug.com/651521 paint/invalidation/svg/tabgroup.svg [ Failure ] +crbug.com/651521 paint/invalidation/svg/window.svg [ Failure ] +crbug.com/651521 paint/invalidation/svg/animated-path-inside-transformed-html.xhtml [ Failure ] +crbug.com/651521 paint/invalidation/svg/js-late-gradient-and-object-creation.svg [ Failure ] +crbug.com/651521 paint/invalidation/svg/js-late-pattern-and-object-creation.svg [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 index 2498558..57370ba 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -845,7 +845,6 @@ Bug(none) fast/multicol/basic-rtl.html [ Failure ] Bug(none) fast/multicol/border-radius-clipped-layer-second-column.html [ Failure ] Bug(none) fast/multicol/border-radius-clipped-layer.html [ Failure ] -Bug(none) fast/multicol/cell-shrinkback.html [ Failure ] Bug(none) fast/multicol/client-rects-rtl.html [ Failure ] Bug(none) fast/multicol/client-rects.html [ Failure ] Bug(none) fast/multicol/column-break-with-balancing.html [ Failure ] @@ -1006,7 +1005,6 @@ Bug(none) fast/multicol/table-caption-with-block.html [ Failure ] Bug(none) fast/multicol/table-cell-content-change-with-decorations.html [ Failure ] Bug(none) fast/multicol/table-margin-collapse.html [ Failure ] -Bug(none) fast/multicol/table-vertical-align.html [ Failure ] Bug(none) fast/multicol/tall-float2.html [ Failure ] Bug(none) fast/multicol/text-shadow-at-column-boundaries.html [ Failure ] Bug(none) fast/multicol/transform-inside-opacity.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 57605949..584d27e 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1225,58 +1225,6 @@ crbug.com/645640 inspector/extensions/extensions-eval.html [ NeedsManualRebaseline ] -crbug.com/655458 imported/wpt/workers/constructors/SharedWorker/undefined-arguments.html [ Failure ] -crbug.com/655458 imported/wpt/workers/baseurl/alpha/worker.html [ Failure ] -crbug.com/655458 imported/wpt/workers/interfaces/SharedWorkerGlobalScope/onconnect.html [ Failure ] -crbug.com/655458 imported/wpt/workers/baseurl/alpha/importScripts.html [ Failure ] -crbug.com/655458 imported/wpt/workers/constructors/SharedWorker/setting-port-members.html [ Failure ] -crbug.com/655458 imported/wpt/workers/baseurl/alpha/xhr.html [ Failure ] -crbug.com/655458 imported/wpt/workers/constructors/SharedWorker/connect-event.html [ Failure ] -crbug.com/655458 imported/wpt/workers/semantics/xhr/001.html [ Failure ] -crbug.com/655458 imported/wpt/workers/semantics/interface-objects/003.html [ Failure ] -crbug.com/655458 imported/wpt/workers/constructors/Worker/unresolvable-url.html [ Failure ] -crbug.com/655458 imported/wpt/workers/semantics/interface-objects/004.html [ Failure ] -crbug.com/655458 imported/wpt/workers/interfaces/WorkerUtils/importScripts/004.html [ Failure ] -crbug.com/655458 imported/wpt/workers/Worker_ErrorEvent_error.htm [ Failure ] -crbug.com/655458 imported/wpt/workers/semantics/reporting-errors/002.html [ Failure ] -crbug.com/655458 imported/wpt/workers/semantics/encodings/004.html [ Failure ] -crbug.com/655458 imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-message.html [ Failure ] -crbug.com/655458 imported/wpt/workers/semantics/reporting-errors/001.html [ Failure ] -crbug.com/655458 imported/wpt/workers/semantics/run-a-worker/003.html [ Failure ] -crbug.com/655458 imported/wpt/workers/Worker_cross_origin_security_err.htm [ Failure ] -crbug.com/655458 imported/wpt/workers/semantics/encodings/003.html [ Failure ] -crbug.com/655458 imported/wpt/workers/constructors/Worker/AbstractWorker.onerror.html [ Failure ] -crbug.com/655458 imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/exception-in-onerror.html [ Failure ] -crbug.com/655458 imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/not-handled.html [ Failure ] -crbug.com/655458 imported/wpt/workers/baseurl/alpha/sharedworker.html [ Failure ] -crbug.com/655458 imported/wpt/workers/Worker_terminate_event_queue.htm [ Timeout ] -crbug.com/655458 imported/wpt/workers/interfaces/WorkerUtils/navigator/language.html [ Failure ] -crbug.com/655458 imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/handled.html [ Failure ] -crbug.com/655458 imported/wpt/workers/constructors/SharedWorker/interface-objects.html [ Failure ] -crbug.com/655458 imported/wpt/workers/constructors/SharedWorker/unresolvable-url.html [ Failure ] -crbug.com/655458 imported/wpt/workers/constructors/SharedWorker/global-members.html [ Failure ] - -crbug.com/655458 imported/wpt/workers/constructors/SharedWorker/same-origin.html [ Timeout ] -crbug.com/655458 imported/wpt/workers/constructors/Worker/same-origin.html [ Timeout ] -crbug.com/655458 imported/wpt/workers/data-url-shared.html [ Timeout ] -crbug.com/655458 imported/wpt/workers/interfaces/WorkerGlobalScope/location/redirect.html [ Timeout ] -crbug.com/655458 imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html [ Timeout ] -crbug.com/655458 imported/wpt/workers/interfaces/WorkerUtils/importScripts/006.html [ Timeout ] -crbug.com/655458 imported/wpt/workers/semantics/multiple-workers/003.html [ Timeout ] -crbug.com/655458 imported/wpt/workers/semantics/multiple-workers/004.html [ Timeout ] -crbug.com/655458 imported/wpt/workers/semantics/multiple-workers/005.html [ Timeout ] -crbug.com/655458 imported/wpt/workers/semantics/multiple-workers/006.html [ Timeout ] -crbug.com/655458 imported/wpt/workers/semantics/multiple-workers/007.html [ Timeout ] -crbug.com/655458 imported/wpt/workers/semantics/multiple-workers/008.html [ Timeout ] -crbug.com/655458 imported/wpt/workers/semantics/navigation/001.html [ Timeout ] -crbug.com/655458 imported/wpt/workers/semantics/navigation/002.html [ Timeout ] -crbug.com/655458 imported/wpt/workers/semantics/reporting-errors/004.html [ Timeout ] -crbug.com/655458 imported/wpt/workers/semantics/xhr/002.html [ Timeout ] -crbug.com/655458 imported/wpt/workers/semantics/xhr/004.html [ Timeout ] - -crbug.com/655458 imported/wpt/workers/semantics/structured-clone/dedicated.html [ Crash Timeout ] -crbug.com/655458 imported/wpt/workers/semantics/structured-clone/shared.html [ Crash Timeout ] - crbug.com/652187 [ Win7 Debug ] http/tests/inspector/network/network-disable-cache-preloads.php [ Failure ] crbug.com/653424 inspector/console/console-format.html [ NeedsManualRebaseline ]
diff --git a/third_party/WebKit/LayoutTests/W3CImportExpectations b/third_party/WebKit/LayoutTests/W3CImportExpectations index edea6c0..d33bc54 100644 --- a/third_party/WebKit/LayoutTests/W3CImportExpectations +++ b/third_party/WebKit/LayoutTests/W3CImportExpectations
@@ -325,7 +325,7 @@ # imported/wpt/webstorage [ Pass ] imported/wpt/webvtt [ Skip ] ## Owners: nhiroki@chromium.org -# imported/wpt/workers [ Skip ] +imported/wpt/workers [ Skip ] # Exceptions for individual files that fail due to bugs in the # upstream tests that we shouldn't bother importing until they are
diff --git a/third_party/WebKit/LayoutTests/fast/block/basic/fieldset-stretch-to-legend-expected.png b/third_party/WebKit/LayoutTests/fast/block/basic/fieldset-stretch-to-legend-expected.png new file mode 100644 index 0000000..893824f --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/block/basic/fieldset-stretch-to-legend-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/block/basic/fieldset-stretch-to-legend-expected.txt b/third_party/WebKit/LayoutTests/fast/block/basic/fieldset-stretch-to-legend-expected.txt index f70480c3..ffc9c682 100644 --- a/third_party/WebKit/LayoutTests/fast/block/basic/fieldset-stretch-to-legend-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/block/basic/fieldset-stretch-to-legend-expected.txt
@@ -1,80 +1,82 @@ -layer at (0,0) size 800x600 clip at (0,0) size 785x600 scrollHeight 898 +layer at (0,0) size 800x600 LayoutView at (0,0) size 800x600 -layer at (0,0) size 785x898 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600 - LayoutBlockFlow {HTML} at (0,0) size 785x898.31 - LayoutBlockFlow {BODY} at (8,8) size 769x880.31 - LayoutFieldset {FIELDSET} at (2,0) size 140x35.59 [border: (8px double #000000)] - LayoutBlockFlow {LEGEND} at (20,0) size 54x12 [bgcolor=#0080004C] - LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 - LayoutFieldset {FIELDSET} at (2,45.59) size 140x35.59 [border: (8px double #000000)] - LayoutBlockFlow {LEGEND} at (20,0) size 112x12 [bgcolor=#0080004C] - LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 - LayoutFieldset {FIELDSET} at (2,91.19) size 140x35.59 [border: (8px double #000000)] - LayoutBlockFlow {LEGEND} at (20,0) size 116x12 [bgcolor=#0080004C] - LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 - LayoutFieldset {FIELDSET} at (2,136.78) size 140x35.59 [border: (8px double #000000)] - LayoutBlockFlow {LEGEND} at (20,0) size 121x12 [bgcolor=#0080004C] - LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 - LayoutFieldset {FIELDSET} at (2,182.38) size 140x35.59 [border: (8px double #000000)] - LayoutBlockFlow {LEGEND} at (8,0) size 54x12 [bgcolor=#0080004C] - LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 - LayoutFieldset {FIELDSET} at (2,227.97) size 140x35.59 [border: (8px double #000000)] - LayoutBlockFlow {LEGEND} at (4,0) size 54x12 [bgcolor=#0080004C] - LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 - LayoutFieldset {FIELDSET} at (2,273.56) size 140x35.59 [border: (8px double #000000)] - LayoutBlockFlow {LEGEND} at (-1,0) size 54x12 [bgcolor=#0080004C] - LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 - LayoutFieldset {FIELDSET} at (2,319.16) size 140x35.59 [border: (8px double #000000)] - LayoutBlockFlow {LEGEND} at (-49,0) size 54x12 [bgcolor=#0080004C] - LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 - LayoutFieldset {FIELDSET} at (2,364.75) size 140x35.59 [border: (8px double #000000)] - LayoutBlockFlow {LEGEND} at (-54,0) size 54x12 [bgcolor=#0080004C] - LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 - LayoutFieldset {FIELDSET} at (2,410.34) size 140x35.59 [border: (8px double #000000)] - LayoutBlockFlow {LEGEND} at (135,0) size 54x12 [bgcolor=#0080004C] - LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 - LayoutFieldset {FIELDSET} at (2,455.94) size 140x35.59 [border: (8px double #000000)] - LayoutBlockFlow {LEGEND} at (140,0) size 54x12 [bgcolor=#0080004C] - LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 - LayoutFieldset {FIELDSET} at (2,501.53) size 184x29.59 [border: (2px groove #C0C0C0)] - LayoutBlockFlow {LEGEND} at (14,0) size 156x12 [border: (1px solid #0000FF)] - LayoutBlockFlow (anonymous) at (14,7.59) size 156x10 - LayoutFieldset {FIELDSET} at (2,541.13) size 184x59.59 [border: (2px groove #C0C0C0)] - LayoutBlockFlow {LEGEND} at (44,0) size 96x12 [border: (1px solid #0000FF)] - LayoutBlockFlow (anonymous) at (14,7.59) size 156x40 - LayoutBlockFlow (anonymous) at (0,810.72) size 769x40 +layer at (0,0) size 800x600 + LayoutBlockFlow {HTML} at (0,0) size 800x600 + LayoutBlockFlow {BODY} at (8,8) size 784x582 + LayoutBlockFlow (floating) {DIV} at (0,0) size 144x501.53 + LayoutFieldset {FIELDSET} at (2,0) size 140x35.59 [border: (8px double #000000)] + LayoutBlockFlow {LEGEND} at (20,0) size 54x12 [bgcolor=#0080004C] + LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 + LayoutFieldset {FIELDSET} at (2,45.59) size 140x35.59 [border: (8px double #000000)] + LayoutBlockFlow {LEGEND} at (20,0) size 112x12 [bgcolor=#0080004C] + LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 + LayoutFieldset {FIELDSET} at (2,91.19) size 140x35.59 [border: (8px double #000000)] + LayoutBlockFlow {LEGEND} at (20,0) size 116x12 [bgcolor=#0080004C] + LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 + LayoutFieldset {FIELDSET} at (2,136.78) size 140x35.59 [border: (8px double #000000)] + LayoutBlockFlow {LEGEND} at (20,0) size 121x12 [bgcolor=#0080004C] + LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 + LayoutFieldset {FIELDSET} at (2,182.38) size 140x35.59 [border: (8px double #000000)] + LayoutBlockFlow {LEGEND} at (8,0) size 54x12 [bgcolor=#0080004C] + LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 + LayoutFieldset {FIELDSET} at (2,227.97) size 140x35.59 [border: (8px double #000000)] + LayoutBlockFlow {LEGEND} at (4,0) size 54x12 [bgcolor=#0080004C] + LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 + LayoutFieldset {FIELDSET} at (2,273.56) size 140x35.59 [border: (8px double #000000)] + LayoutBlockFlow {LEGEND} at (-1,0) size 54x12 [bgcolor=#0080004C] + LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 + LayoutFieldset {FIELDSET} at (2,319.16) size 140x35.59 [border: (8px double #000000)] + LayoutBlockFlow {LEGEND} at (-49,0) size 54x12 [bgcolor=#0080004C] + LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 + LayoutFieldset {FIELDSET} at (2,364.75) size 140x35.59 [border: (8px double #000000)] + LayoutBlockFlow {LEGEND} at (-54,0) size 54x12 [bgcolor=#0080004C] + LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 + LayoutFieldset {FIELDSET} at (2,410.34) size 140x35.59 [border: (8px double #000000)] + LayoutBlockFlow {LEGEND} at (135,0) size 54x12 [bgcolor=#0080004C] + LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 + LayoutFieldset {FIELDSET} at (2,455.94) size 140x35.59 [border: (8px double #000000)] + LayoutBlockFlow {LEGEND} at (140,0) size 54x12 [bgcolor=#0080004C] + LayoutBlockFlow (anonymous) at (20,13.59) size 100x4 + LayoutBlockFlow {DIV} at (450,0) size 334x408.78 LayoutFieldset {FIELDSET} at (2,0) size 184x29.59 [border: (2px groove #C0C0C0)] LayoutBlockFlow {LEGEND} at (14,0) size 156x12 [border: (1px solid #0000FF)] LayoutBlockFlow (anonymous) at (14,7.59) size 156x10 - LayoutText {#text} at (0,0) size 0x0 - LayoutFieldset {FIELDSET} at (2,850.72) size 128x29.59 [border: (2px groove #C0C0C0)] - LayoutBlockFlow {LEGEND} at (14,0) size 156x12 [border: (1px solid #0000FF)] - LayoutBlockFlow (anonymous) at (14,7.59) size 100x10 -layer at (8,619) size 100x40 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600 - LayoutBlockFlow (relative positioned) {DIV} at (0,610.72) size 100x40 + LayoutFieldset {FIELDSET} at (2,39.59) size 184x89.59 [border: (2px groove #C0C0C0)] + LayoutBlockFlow {LEGEND} at (44,30) size 96x12 [border: (1px solid #0000FF)] + LayoutBlockFlow (anonymous) at (14,7.59) size 156x70 + LayoutBlockFlow (anonymous) at (0,339.19) size 334x40 + LayoutFieldset {FIELDSET} at (2,0) size 184x29.59 [border: (2px groove #C0C0C0)] + LayoutBlockFlow {LEGEND} at (14,0) size 156x12 [border: (1px solid #0000FF)] + LayoutBlockFlow (anonymous) at (14,7.59) size 156x10 + LayoutText {#text} at (0,0) size 0x0 + LayoutFieldset {FIELDSET} at (2,379.19) size 128x29.59 [border: (2px groove #C0C0C0)] + LayoutBlockFlow {LEGEND} at (14,0) size 156x12 [border: (1px solid #0000FF)] + LayoutBlockFlow (anonymous) at (14,7.59) size 100x10 +layer at (458,147) size 100x40 + LayoutBlockFlow (relative positioned) {DIV} at (0,139.19) size 100x40 LayoutFieldset {FIELDSET} at (2,0) size 184x29.59 [border: (2px groove #C0C0C0)] LayoutBlockFlow {LEGEND} at (14,0) size 156x12 [border: (1px solid #0000FF)] LayoutBlockFlow (anonymous) at (14,7.59) size 156x10 -layer at (8,659) size 300x40 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600 - LayoutBlockFlow (relative positioned) {DIV} at (0,650.72) size 300x40 +layer at (458,187) size 300x40 + LayoutBlockFlow (relative positioned) {DIV} at (0,179.19) size 300x40 LayoutFieldset {FIELDSET} at (58,0) size 184x29.59 [border: (2px groove #C0C0C0)] LayoutBlockFlow {LEGEND} at (14,0) size 156x12 [border: (1px solid #0000FF)] LayoutBlockFlow (anonymous) at (14,7.59) size 156x10 -layer at (8,699) size 100x40 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600 - LayoutBlockFlow (relative positioned) {DIV} at (0,690.72) size 100x40 -layer at (10,699) size 184x30 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600 +layer at (458,227) size 100x40 + LayoutBlockFlow (relative positioned) {DIV} at (0,219.19) size 100x40 +layer at (460,227) size 184x30 LayoutFieldset (positioned) {FIELDSET} at (2,0) size 184x29.59 [border: (2px groove #C0C0C0)] LayoutBlockFlow {LEGEND} at (14,0) size 156x12 [border: (1px solid #0000FF)] LayoutBlockFlow (anonymous) at (14,7.59) size 156x10 -layer at (8,739) size 769x40 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600 - LayoutBlockFlow (relative positioned) {DIV} at (0,730.72) size 769x40 -layer at (10,739) size 184x30 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600 +layer at (458,267) size 334x40 + LayoutBlockFlow (relative positioned) {DIV} at (0,259.19) size 334x40 +layer at (460,267) size 184x30 LayoutFieldset (positioned) {FIELDSET} at (2,0) size 184x29.59 [border: (2px groove #C0C0C0)] LayoutBlockFlow {LEGEND} at (14,0) size 156x12 [border: (1px solid #0000FF)] LayoutBlockFlow (anonymous) at (14,7.59) size 156x10 -layer at (8,779) size 300x40 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600 - LayoutBlockFlow (relative positioned) {DIV} at (0,770.72) size 300x40 -layer at (110,779) size 184x30 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600 +layer at (458,307) size 300x40 + LayoutBlockFlow (relative positioned) {DIV} at (0,299.19) size 300x40 +layer at (560,307) size 184x30 LayoutFieldset (positioned) {FIELDSET} at (102,0) size 184x29.59 [border: (2px groove #C0C0C0)] LayoutBlockFlow {LEGEND} at (14,0) size 156x12 [border: (1px solid #0000FF)] LayoutBlockFlow (anonymous) at (14,7.59) size 156x10
diff --git a/third_party/WebKit/LayoutTests/fast/block/basic/fieldset-stretch-to-legend.html b/third_party/WebKit/LayoutTests/fast/block/basic/fieldset-stretch-to-legend.html index db24e16..a551a46 100644 --- a/third_party/WebKit/LayoutTests/fast/block/basic/fieldset-stretch-to-legend.html +++ b/third_party/WebKit/LayoutTests/fast/block/basic/fieldset-stretch-to-legend.html
@@ -7,79 +7,86 @@ fieldset.render { border: 8px double; } fieldset.render legend { height: 12px; width: 50px; background-color: rgba(0, 128, 0, 0.3); border: none; } div.rel { position: relative; height: 40px; } + #col1 { float: left; } + #col2 { margin-left: 450px; } </style> </head> <body> <!-- border rendering tests --> - <fieldset class="render" style="width: 100px;"> - <legend></legend> - </fieldset> - <fieldset class="render" style="width: 100px;"> - <legend style="width: 108%;"></legend> - </fieldset> - <fieldset class="render" style="width: 100px;"> - <legend style="width: 112%;"></legend> - </fieldset> - <fieldset class="render" style="width: 100px;"> - <legend style="width: 117%;"></legend> - </fieldset> - <fieldset class="render" style="width: 100px;"> - <legend style="margin-left: -12px;"></legend> - </fieldset> - <fieldset class="render" style="width: 100px;"> - <legend style="margin-left: -16px;"></legend> - </fieldset> - <fieldset class="render" style="width: 100px;"> - <legend style="margin-left: -21px;"></legend> - </fieldset> - <fieldset class="render" style="width: 100px;"> - <legend style="margin-left: -69px;"></legend> - </fieldset> - <fieldset class="render" style="width: 100px;"> - <legend style="margin-left: -74px;"></legend> - </fieldset> - <fieldset class="render" style="width: 100px;"> - <legend style="margin-left: 115%;"></legend> - </fieldset> - <fieldset class="render" style="width: 100px;"> - <legend style="margin-left: 120%;"></legend> - </fieldset> + <div id="col1"> + <!-- border rendering tests --> + <fieldset class="render" style="width: 100px;"> + <legend></legend> + </fieldset> + <fieldset class="render" style="width: 100px;"> + <legend style="width: 108%;"></legend> + </fieldset> + <fieldset class="render" style="width: 100px;"> + <legend style="width: 112%;"></legend> + </fieldset> + <fieldset class="render" style="width: 100px;"> + <legend style="width: 117%;"></legend> + </fieldset> + <fieldset class="render" style="width: 100px;"> + <legend style="margin-left: -12px;"></legend> + </fieldset> + <fieldset class="render" style="width: 100px;"> + <legend style="margin-left: -16px;"></legend> + </fieldset> + <fieldset class="render" style="width: 100px;"> + <legend style="margin-left: -21px;"></legend> + </fieldset> + <fieldset class="render" style="width: 100px;"> + <legend style="margin-left: -69px;"></legend> + </fieldset> + <fieldset class="render" style="width: 100px;"> + <legend style="margin-left: -74px;"></legend> + </fieldset> + <fieldset class="render" style="width: 100px;"> + <legend style="margin-left: 115%;"></legend> + </fieldset> + <fieldset class="render" style="width: 100px;"> + <legend style="margin-left: 120%;"></legend> + </fieldset> + </div> <!-- layout tests --> - <fieldset style="width: 100px;"> - <legend style="width: 150px;"></legend> - </fieldset> - <fieldset style="width: 100px;"> - <legend style="width: 90px; margin: 30px;"></legend> - </fieldset> - <div class="rel" style="width: 100px;"> - <fieldset> + <div id="col2"> + <fieldset style="width: 100px;"> <legend style="width: 150px;"></legend> </fieldset> - </div> - <div class="rel" style="width: 300px;"> - <fieldset style="width: 100; margin: auto;"> + <fieldset style="width: 100px;"> + <legend style="width: 90px; margin: 30px;"></legend> + </fieldset> + <div class="rel" style="width: 100px;"> + <fieldset> + <legend style="width: 150px;"></legend> + </fieldset> + </div> + <div class="rel" style="width: 300px;"> + <fieldset style="width: 100; margin: auto;"> + <legend style="width: 150px;"></legend> + </fieldset> + </div> + <div class="rel" style="width: 100px;"> + <fieldset style="position: absolute;"> + <legend style="width: 150px;"></legend> + </fieldset> + </div> + <div class="rel"> + <fieldset style="position: absolute; width: 100px;"> + <legend style="width: 150px;"></legend> + </fieldset> + </div> + <div class="rel" style="width: 300px;"> + <fieldset style="position: absolute; left: 100px; right: 100px;"> + <legend style="width: 150px;"></legend> + </fieldset> + </div> + <fieldset style="display: inline; width: 100px;"> <legend style="width: 150px;"></legend> </fieldset> - </div> - <div class="rel" style="width: 100px;"> - <fieldset style="position: absolute;"> - <legend style="width: 150px;"></legend> + <fieldset style="width: 100px;"> + <legend style="width: 150%;"></legend> </fieldset> </div> - <div class="rel"> - <fieldset style="position: absolute; width: 100px;"> - <legend style="width: 150px;"></legend> - </fieldset> - </div> - <div class="rel" style="width: 300px;"> - <fieldset style="position: absolute; left: 100px; right: 100px;"> - <legend style="width: 150px;"></legend> - </fieldset> - </div> - <fieldset style="display: inline; width: 100px;"> - <legend style="width: 150px;"></legend> - </fieldset> - <fieldset style="width: 100px;"> - <legend style="width: 150%;"></legend> - </fieldset> </body>
diff --git a/third_party/WebKit/LayoutTests/fast/borders/fieldsetBorderRadius-expected.png b/third_party/WebKit/LayoutTests/fast/borders/fieldsetBorderRadius-expected.png index eacd0f6..3fb07f1 100644 --- a/third_party/WebKit/LayoutTests/fast/borders/fieldsetBorderRadius-expected.png +++ b/third_party/WebKit/LayoutTests/fast/borders/fieldsetBorderRadius-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/borders/fieldsetBorderRadius-expected.txt b/third_party/WebKit/LayoutTests/fast/borders/fieldsetBorderRadius-expected.txt index 9bc709f..109da2c 100644 --- a/third_party/WebKit/LayoutTests/fast/borders/fieldsetBorderRadius-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/borders/fieldsetBorderRadius-expected.txt
@@ -49,8 +49,8 @@ LayoutBlockFlow {LEGEND} at (14,0) size 156x12 [border: (1px solid #0000FF)] LayoutBlockFlow (anonymous) at (14,7.59) size 156x20 LayoutFieldset {FIELDSET} at (2,49.59) size 184x39.59 [border: (2px groove #C0C0C0)] - LayoutBlockFlow {LEGEND} at (44,0) size 96x12 [border: (1px solid #0000FF)] - LayoutBlockFlow (anonymous) at (14,7.59) size 156x40 + LayoutBlockFlow {LEGEND} at (44,30) size 96x12 [border: (1px solid #0000FF)] + LayoutBlockFlow (anonymous) at (14,7.59) size 156x70 LayoutBlockFlow (anonymous) at (0,299.19) size 334x50 LayoutFieldset {FIELDSET} at (2,0) size 184x39.59 [border: (2px groove #C0C0C0)] LayoutBlockFlow {LEGEND} at (14,0) size 156x12 [border: (1px solid #0000FF)]
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-change-fit-content-argument-expected.txt b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-change-fit-content-argument-expected.txt new file mode 100644 index 0000000..91b4bab --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-change-fit-content-argument-expected.txt
@@ -0,0 +1,11 @@ +This test checks that grid-template-{rows|columns} with fit-content() tracks recomputes the tracks when the fit-content() argument is modified. +XXXX XXX XX X X +PASS +PASS +PASS +PASS +XXXX XXX XX X X +PASS +PASS +PASS +PASS
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-change-fit-content-argument.html b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-change-fit-content-argument.html new file mode 100644 index 0000000..9ac99c6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-change-fit-content-argument.html
@@ -0,0 +1,64 @@ +<!DOCTYPE html> +<link href="resources/grid.css" rel="stylesheet"> +<style> +.grid { + width: fit-content; + position: relative; + justify-content: start; + align-content: start; + font: 25px/1 Ahem; +} + +.verticalLR { + writing-mode: vertical-lr; +} +</style> +<!-- Explicitly not using layout-th because it does not allow multiple checkLayout(). --> +<script src="../../resources/check-layout.js"></script> +<script> +function setGridTemplate(id, gridTemplateRows, gridTemplateColumns) +{ + var gridElement = document.getElementById(id); + gridElement.style.gridTemplateRows = gridTemplateRows; + gridElement.style.gridTemplateColumns = gridTemplateColumns; +} + +function testGridItemDefinitions(gridItemData) +{ + var item = document.getElementById(gridItemData.id); + item.setAttribute("data-expected-width", gridItemData.width); + item.setAttribute("data-expected-height", gridItemData.height); + item.setAttribute("data-offset-x", gridItemData.x); + item.setAttribute("data-offset-y", gridItemData.y); + + checkLayout(".grid"); +} + +function testChangingGridDefinitions() +{ + // Test changing the argument of fit-content() tracks. + setGridTemplate("grid1", "none", "fit-content(100px)"); + testGridItemDefinitions({"id": "item1", "width": "100", "height": "100", "x": "0", "y": "0" }); + + setGridTemplate("grid1", "none", "fit-content(150px)"); + testGridItemDefinitions({"id": "item1", "width": "150", "height": "75", "x": "0", "y": "0" }); + + setGridTemplate("grid2", "fit-content(100px)", "none"); + testGridItemDefinitions({"id": "item2", "width": "100", "height": "100", "x": "0", "y": "0" }); + + setGridTemplate("grid2", "fit-content(150px)", "none"); + testGridItemDefinitions({"id": "item2", "width": "75", "height": "150", "x": "0", "y": "0" }); +} + +window.addEventListener("load", testChangingGridDefinitions, false); +</script> + +<div>This test checks that grid-template-{rows|columns} with fit-content() tracks recomputes the tracks when the fit-content() argument is modified.</div> + +<div id="grid1" class="grid"> + <div id="item1" class="autoRowAutoColumn">XXXX XXX XX X X</div> +</div> + +<div id="grid2" class="grid"> + <div id="item2" class="autoRowAutoColumn verticalLR">XXXX XXX XX X X</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/fieldset/legend-margin-before-in-fieldset-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/fieldset/legend-margin-before-in-fieldset-expected.txt new file mode 100644 index 0000000..f1150ec9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/forms/fieldset/legend-margin-before-in-fieldset-expected.txt
@@ -0,0 +1,2 @@ +Legend in fieldset +PASS
diff --git a/third_party/WebKit/LayoutTests/fast/forms/fieldset/legend-margin-before-in-fieldset.html b/third_party/WebKit/LayoutTests/fast/forms/fieldset/legend-margin-before-in-fieldset.html new file mode 100644 index 0000000..0349290 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/forms/fieldset/legend-margin-before-in-fieldset.html
@@ -0,0 +1,8 @@ +<!DOCTYPE html> +<script src="../../../resources/check-layout.js"></script> +<fieldset id="fieldset"> + <legend data-offset-y="108" style="margin-top: 100px">Legend in fieldset</legend> +</fieldset> +<script> + checkLayout("#fieldset"); +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/cell-shrinkback-expected.html b/third_party/WebKit/LayoutTests/fast/multicol/cell-shrinkback-expected.html deleted file mode 100644 index 7cb2fd2..0000000 --- a/third_party/WebKit/LayoutTests/fast/multicol/cell-shrinkback-expected.html +++ /dev/null
@@ -1,7 +0,0 @@ -<!DOCTYPE html> -<div style="height: 100px; width: 200px; border: solid;position:relative"> - <div style="left:25px; bottom:0; position:absolute; height:45px; width:3em; background-color:orange"></div> - <div style="border-bottom:solid; position:absolute; right:0px; width:100px"> - <div style="background-color:orange; float:left;margin-left:25px; width:3em;">Text</div> - </div> -</div>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/cell-shrinkback.html b/third_party/WebKit/LayoutTests/fast/multicol/cell-shrinkback.html deleted file mode 100644 index 1df68b6..0000000 --- a/third_party/WebKit/LayoutTests/fast/multicol/cell-shrinkback.html +++ /dev/null
@@ -1,14 +0,0 @@ -<!DOCTYPE html> -<style> - body { overflow: hidden; } /* Disable auto-scrollbars, to hide crbug.com/534751 */ -</style> -<div style="height: 100px; width: 200px; border: solid; -webkit-columns:2; -webkit-column-gap:0; columns:2; column-gap:0; column-fill:auto;"> - <div style="height: 55px;"></div> - <table cellspacing=0 cellpadding=0> - <tr> - <td><div style="height: 50px; width: 25px;"></div></td> - <td style="width:3em; background-color: orange;" valign=bottom>Text</td> - </tr> - </table> - <div style="border-top: solid;"></div> -</div>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/table-vertical-align-expected.html b/third_party/WebKit/LayoutTests/fast/multicol/table-vertical-align-expected.html deleted file mode 100644 index c912adab..0000000 --- a/third_party/WebKit/LayoutTests/fast/multicol/table-vertical-align-expected.html +++ /dev/null
@@ -1,71 +0,0 @@ -<!DOCTYPE html> -<style> - .mc { width:520px; height:80px; font-size:12px; line-height:20px; background:#ddd; } - .mc span { font-size:2em; line-height:30px; } -</style> - -<p>The big text should be in the first column, and baseline-aligned with the line in its neighbor cell on the left:</p> -<div class="mc"> - <div style="float:left; padding-left:10px; padding-top:10px; width:270px;"> - <div style="display:inline-block; width:30px;"> - line<br> - <!-- The baseline of an inline-block is the baseline of the last in-flow line. So make - sure the first line is also the last in-flow line :-P --> - <div style="position:absolute;"> - line<br> - line - </div> - </div><span style="margin-left:15px;">1st column</span> - </div> - <div style="float:left;"> - line<br> - line<br> - line<br> - </div> -</div> - -<hr> - -<p>The big text should be near the top in the first column:</p> -<div class="mc"> - <div style="float:left; padding-left:10px; padding-top:10px; width:270px;"> - <div style="float:left; width:30px;">line<br>line<br>line</div> - <span style="margin-left:15px;">1st column</span> - </div> - <div style="float:left;"> - line<br> - line<br> - line<br> - </div> -</div> - -<hr> - -<p>The big text should be at the top in the second column:</p> -<div class="mc"> - <div style="float:left; padding-left:10px; padding-top:10px; width:270px;"> - line<br> - line<br> - line<br> - </div> - <div style="float:left; width:220px;"> - <div style="float:left; width:30px;">line<br>line<br>line</div> - <span style="margin-left:15px;">2nd column</span> - </div> -</div> - -<hr> - -<p>The big text should be near the bottom in the second column:</p> -<div class="mc"> - <div style="float:left; padding-left:10px; padding-top:10px; width:270px;"> - line<br> - line<br> - line<br> - </div> - <div style="float:left; width:200px;"> - <div style="float:left; width:30px;">line<br>line<br>line</div> - <div style="height:35px;"></div> - <span style="margin-left:15px;">2nd column</span> - </div> -</div>
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/table-vertical-align.html b/third_party/WebKit/LayoutTests/fast/multicol/table-vertical-align.html deleted file mode 100644 index 231edb6..0000000 --- a/third_party/WebKit/LayoutTests/fast/multicol/table-vertical-align.html +++ /dev/null
@@ -1,91 +0,0 @@ -<!DOCTYPE html> -<style> - body { overflow: hidden; } /* Disable auto-scrollbars, to hide crbug.com/534751 */ - .mc { -webkit-columns:2; -webkit-column-gap:20px; column-fill:auto; overflow:hidden; width:520px; height:80px; font-size:12px; line-height:20px; background:#ddd; } - table { border-spacing:5px; } - td:first-child { width:30px; } - td { padding:5px; } - .mc span { font-size:2em; line-height:30px; } -</style> - -<p>The big text should be in the first column, and baseline-aligned with the line in its neighbor cell on the left:</p> -<div class="mc"> - <table> - <tr style="vertical-align:baseline"> - <td> - line<br> - line<br> - line<br> - line<br> - line<br> - line<br> - </td> - <td> - <span>1st column</span> - </td> - </tr> - </table> -</div> - -<hr> - -<p>The big text should be near the top in the first column:</p> -<div class="mc"> - <table> - <tr style="vertical-align:top"> - <td> - line<br> - line<br> - line<br> - line<br> - line<br> - line<br> - </td> - <td> - <span>1st column</span> - </td> - </tr> - </table> -</div> - -<hr> - -<p>The big text should be at the top in the second column:</p> -<div class="mc"> - <table> - <tr style="vertical-align:middle"> - <td> - line<br> - line<br> - line<br> - line<br> - line<br> - line<br> - </td> - <td> - <span>2nd column</span> - </td> - </tr> - </table> -</div> - -<hr> - -<p>The big text should be near the bottom in the second column:</p> -<div class="mc"> - <table> - <tr style="vertical-align:bottom"> - <td> - line<br> - line<br> - line<br> - line<br> - line<br> - line<br> - </td> - <td> - <span>2nd column</span> - </td> - </tr> - </table> -</div>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/fragmented-table-cell-expected.html b/third_party/WebKit/LayoutTests/fragmentation/fragmented-table-cell-expected.html new file mode 100644 index 0000000..35006d27 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fragmentation/fragmented-table-cell-expected.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<style> + .cell { float:left; width:1em; } +</style> +<p>The word "PASS" should be seen below, with large letter + spacing. There should be a blue rectangle snapped to the blue + line. There should be no red.</p> +<div style="width:15em; line-height:20px; border-top:1px solid blue;"> + <div style="float:left; margin-left:6em; width:1em; height:1em; background:blue;"></div> + <br> + <br> + <div class="cell">P</div> + <div class="cell">A</div> + <div class="cell">S</div> + <div class="cell">S</div> +</div>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/fragmented-table-cell.html b/third_party/WebKit/LayoutTests/fragmentation/fragmented-table-cell.html new file mode 100644 index 0000000..c777ca5b --- /dev/null +++ b/third_party/WebKit/LayoutTests/fragmentation/fragmented-table-cell.html
@@ -0,0 +1,30 @@ +<!DOCTYPE html> +<style> + td { width:1em; } +</style> +<p>The word "PASS" should be seen below, with large letter + spacing. There should be a blue rectangle snapped to the blue + line. There should be no red.</p> +<div style="columns:3; column-gap:0; column-fill:auto; width:15em; height:90px; line-height:20px; orphans:1; widows:1; border-top:1px solid blue;"> + <br> + <br> + <table cellpadding="0" cellspacing="0" style="background:white;"> + <tr> + <td style="vertical-align:bottom;"> + P + </td> + <td style="vertical-align:baseline; background:red;"> + <div style="background:white;"> + A<br><br> + <div style="break-inside:avoid; width:100%; height:1em; background:blue;"></div> + </div> + </td> + <td style="vertical-align:top;"> + S + </td> + <td style="vertical-align:middle;"> + S + </td> + </tr> + </table> +</div>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/README.md b/third_party/WebKit/LayoutTests/imported/wpt/workers/README.md deleted file mode 100644 index 3a1c58f..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/README.md +++ /dev/null
@@ -1,8 +0,0 @@ -This directory contains the Web Workers test suite. - -To run this test suite within a browser, go to: <http://w3c-test.org/web-platform-tests/master/workers/>. - -The latest Editor's Draft of Web Workers is: <http://dev.w3.org/html5/workers/>. - -The latest W3C Technical Report of Web Workers is <http://www.w3.org/TR/workers/>. -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_colno.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_colno.htm deleted file mode 100644 index 793d6c1..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_colno.htm +++ /dev/null
@@ -1,18 +0,0 @@ -<!DOCTYPE html> -<title> WorkerGlobalScope onerror event handler argument: col </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -// The worker events races with the window's load event; if the worker events -// arrive first, the harness will detect the error event and fail the test. -setup({ allow_uncaught_exception: true }); - -async_test(function(t) { - var worker = new Worker('./support/ErrorEvent.js'); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(typeof e.data.colno, "number"); - }); - worker.postMessage("Error Message"); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_filename.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_filename.htm deleted file mode 100644 index e165a23..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_filename.htm +++ /dev/null
@@ -1,20 +0,0 @@ -<!DOCTYPE html> -<title> WorkerGlobalScope onerror event handler argument: location </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -// The worker events races with the window's load event; if the worker events -// arrive first, the harness will detect the error event and fail the test. -setup({ allow_uncaught_exception: true }); - -async_test(function(t) { - var worker = new Worker('./support/ErrorEvent.js'); - worker.onmessage = t.step_func_done(function(e) { - var href = location.href; - var expected = href.substring(0, href.lastIndexOf('/')) + '/support/ErrorEvent.js'; - assert_equals(e.data.filename, expected); - }); - worker.postMessage("Error Message"); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_lineno.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_lineno.htm deleted file mode 100644 index dfbc5146..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_lineno.htm +++ /dev/null
@@ -1,18 +0,0 @@ -<!DOCTYPE html> -<title> WorkerGlobalScope onerror event handler argument: line </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -// The worker events races with the window's load event; if the worker events -// arrive first, the harness will detect the error event and fail the test. -setup({ allow_uncaught_exception: true }); - -async_test(function(t) { - var worker = new Worker('./support/ErrorEvent.js'); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data.lineno, 3); - }); - worker.postMessage("Error Message"); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_message.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_message.htm deleted file mode 100644 index bc1d2c4..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_message.htm +++ /dev/null
@@ -1,19 +0,0 @@ -<!DOCTYPE html> -<title> WorkerGlobalScope onerror event handler argument: message </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -// The worker events races with the window's load event; if the worker events -// arrive first, the harness will detect the error event and fail the test. -setup({ allow_uncaught_exception: true }); - -async_test(function(t) { - var message = 'Error Message'; - var worker = new Worker('./support/ErrorEvent.js'); - worker.onmessage = t.step_func_done(function(e) { - assert_greater_than(e.data.message.indexOf(message), -1); - }); - worker.postMessage(message); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_close.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_close.htm deleted file mode 100644 index 2ad5205..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_close.htm +++ /dev/null
@@ -1,17 +0,0 @@ -<!DOCTYPE html> -<title> WorkerGlobalScope close(): clear events queue </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker('./support/WorkerClose.js'); - worker.onmessage = t.step_func(function(e) { - assert_equals(e.data, "ping"); - worker.onmessage = t.unreached_func("Unexpected message event"); - worker.postMessage("pong"); - setTimeout(t.step_func_done(), 100); - }); - worker.postMessage("ping"); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_importScripts.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_importScripts.htm deleted file mode 100644 index 1a3616d..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_importScripts.htm +++ /dev/null
@@ -1,14 +0,0 @@ -<!DOCTYPE html> -<title> WorkerGlobalScope API: importScripts() </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker("./support/ImportScripts.js"); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data, "Pass"); - }); - worker.postMessage("ping"); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_importScripts_NetworkErr.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_importScripts_NetworkErr.htm deleted file mode 100644 index 36fe6e0..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_importScripts_NetworkErr.htm +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title> importScripts() with non-existent script file </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker("./support/ImportScriptsNetworkErr.js"); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data, "Pass"); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_setInterval.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_setInterval.htm deleted file mode 100644 index 4e147fbf..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_setInterval.htm +++ /dev/null
@@ -1,20 +0,0 @@ -<!DOCTYPE html> -<title> WorkerGlobalScope API: setInterval() </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var result = []; - var worker = new Worker('./support/Timer.js'); - worker.onmessage = t.step_func(function(e) { - result.push(e.data); - if (result.length == 3) { - assert_array_equals(result, ["hello", "worker", "worker"]); - worker.onmessage = t.unreached_func('Unexpected message event'); - setTimeout(t.step_func_done(), 100); - } - }); - worker.postMessage("IntervalHandler"); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_setTimeout.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_setTimeout.htm deleted file mode 100644 index 89fdf3d7..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_setTimeout.htm +++ /dev/null
@@ -1,20 +0,0 @@ -<!DOCTYPE html> -<title> WorkerGlobalScope API: setTimeout() </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var result = []; - var worker = new Worker('./support/Timer.js'); - worker.onmessage = t.step_func(function(e) { - result.push(e.data); - if (result.length == 3) { - assert_array_equals(result, ["hello", "worker", "worker"]); - worker.onmessage = t.unreached_func('Unexpected message event'); - setTimeout(t.step_func_done(), 100); - } - }); - worker.postMessage("TimeoutHandler"); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation.htm deleted file mode 100644 index a74f13a8..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation.htm +++ /dev/null
@@ -1,15 +0,0 @@ -<!DOCTYPE html> -<title> WorkerLocation object </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker('./support/WorkerLocation.js'); - worker.onmessage = t.step_func_done(function(e) { - var href = window.location.href; - var ExpectedResult = href.substring(0, href.lastIndexOf('/')) + '/support/WorkerLocation.js'; - assert_equals(e.data.location, ExpectedResult); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hash.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hash.htm deleted file mode 100644 index 74a424e..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hash.htm +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title> WorkerLocation URL decomposition IDL attribute: hash </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker("./support/WorkerLocation.js#HashString"); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data.hash, "#HashString"); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hash_encoding.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hash_encoding.htm deleted file mode 100644 index b2a171a..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hash_encoding.htm +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title> WorkerLocation.hash with url encoding string </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker("./support/WorkerLocation.js#question%3f"); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data.hash, "#question%3f"); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hash_nonexist.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hash_nonexist.htm deleted file mode 100644 index 2d898c0..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hash_nonexist.htm +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title> WorkerLocation.hash with no <fragment> component </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker('./support/WorkerLocation.js'); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data.hash, ""); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_host.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_host.htm deleted file mode 100644 index 53286ddf..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_host.htm +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title> WorkerLocation URL decomposition IDL attribute: host </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker('./support/WorkerLocation.js'); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data.host, location.host); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hostname.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hostname.htm deleted file mode 100644 index 9725080..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hostname.htm +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title> WorkerLocation URL decomposition IDL attribute: hostname </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker('./support/WorkerLocation.js'); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data.hostname, location.hostname); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_href.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_href.htm deleted file mode 100644 index 3ed1dbd..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_href.htm +++ /dev/null
@@ -1,15 +0,0 @@ -<!DOCTYPE html> -<title> WorkerLocation href attribute </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker("./support/WorkerLocation.js?srch%20#hash"); - worker.onmessage = t.step_func_done(function(e) { - var href = location.href; - var expected = href.substring(0, href.lastIndexOf('/')) + "/support/WorkerLocation.js?srch%20#hash"; - assert_equals(e.data.href, expected); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_pathname.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_pathname.htm deleted file mode 100644 index 3469845..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_pathname.htm +++ /dev/null
@@ -1,15 +0,0 @@ -<!DOCTYPE html> -<title> WorkerLocation URL decomposition IDL attribute: pathname </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker('./support/WorkerLocation.js'); - worker.onmessage = t.step_func_done(function(e) { - var pathname = location.pathname; - var expected = pathname.substring(0, pathname.lastIndexOf('/')) + '/support/WorkerLocation.js'; - assert_equals(e.data.pathname, expected); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_port.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_port.htm deleted file mode 100644 index ef86cfa..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_port.htm +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title> WorkerLocation URL decomposition IDL attribute: port </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker('./support/WorkerLocation.js'); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data.port, location.port); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_protocol.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_protocol.htm deleted file mode 100644 index f792dee5..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_protocol.htm +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title> WorkerLocation URL decomposition IDL attribute: protocol </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker('./support/WorkerLocation.js'); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data.protocol, location.protocol); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search.htm deleted file mode 100644 index bc6add8..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search.htm +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title> WorkerLocation URL decomposition IDL attribute: search </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker('./support/WorkerLocation.js?SearchString'); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data.search, '?SearchString'); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search_empty.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search_empty.htm deleted file mode 100644 index a32d430..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search_empty.htm +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title> WorkerLocation.search with empty <query> </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker("./support/WorkerLocation.js?"); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data.search, ""); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search_fragment.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search_fragment.htm deleted file mode 100644 index 3ec4cff..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search_fragment.htm +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title> WorkerLocation.search with <fragment> in <query> </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker('./support/WorkerLocation.js?test#'); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data.search, "?test"); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search_nonexist.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search_nonexist.htm deleted file mode 100644 index 9907e647..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search_nonexist.htm +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title> WorkerLocation.search with no <query> component </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker('./support/WorkerLocation.js'); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data.search, ""); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_appName.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_appName.htm deleted file mode 100644 index 832c46f..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_appName.htm +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title> WorkerNavigator appName </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker("./support/WorkerNavigator.js"); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data.appName, navigator.appName); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_appVersion.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_appVersion.htm deleted file mode 100644 index 7deaa42..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_appVersion.htm +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title> WorkerNavigator appVersion </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker("./support/WorkerNavigator.js"); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data.appVersion, navigator.appVersion); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_onLine.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_onLine.htm deleted file mode 100644 index f9e819b..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_onLine.htm +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title> WorkerNavigator.onLine </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker("./support/WorkerNavigator.js"); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data.onLine, navigator.onLine); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_platform.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_platform.htm deleted file mode 100644 index 3a6de80..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_platform.htm +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title> WorkerNavigator.platform </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker("./support/WorkerNavigator.js"); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data.platform, navigator.platform); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_userAgent.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_userAgent.htm deleted file mode 100644 index 8a34fb48..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_userAgent.htm +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title> WorkerNavigator.userAgent </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker("./support/WorkerNavigator.js"); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data.userAgent, navigator.userAgent); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_bubbles_cancelable.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_bubbles_cancelable.htm deleted file mode 100644 index 4619ee7b..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_bubbles_cancelable.htm +++ /dev/null
@@ -1,22 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>Web Workers: Worker ErrorEvent - bubbles, cancelable</title> -<link rel="author" title="Intel" href="http://www.intel.com"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -// The worker events races with the window's load event; if the worker events -// arrive first, the harness will detect the error event and fail the test. -setup({ allow_uncaught_exception: true }); - -async_test(function(t) { - var worker = new Worker('./support/ErrorEvent.js'); - worker.onerror = t.step_func_done(function(e) { - assert_false(e.bubbles, "onerror on worker doesn't bubble"); - assert_true(e.cancelable, "onerror on worker is cancelable"); - }); - worker.postMessage("Error Message"); -}, "ErrorEvent on worker doesn't bubble and is cancelable"); - -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_error.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_error.htm deleted file mode 100644 index 1c1257d1..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_error.htm +++ /dev/null
@@ -1,29 +0,0 @@ -<!doctype html> -<meta charset=utf-8> -<title></title> -<script src=/resources/testharness.js></script> -<script src=/resources/testharnessreport.js></script> -<script> -var t1 = async_test("Error handler outside the worker should not see the error value"); -var t2 = async_test("Error handlers inside a worker should see the error value"); - -test(function() { - var worker = new Worker("support/ErrorEvent-error.js"); - worker.onerror = t1.step_func_done(function(e) { - assert_true(/hello/.test(e.message)); - assert_equals(e.error, null); - }); - - var messages = 0; - worker.onmessage = t2.step_func(function(e) { - ++messages; - var data = e.data; - assert_true(data.source == "onerror" || - data.source == "event listener"); - assert_equals(data.value, "hello"); - if (messages == 2) { - t2.done(); - } - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_filename.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_filename.htm deleted file mode 100644 index 0faef6fea..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_filename.htm +++ /dev/null
@@ -1,20 +0,0 @@ -<!DOCTYPE html> -<title> AbstractWorker ErrorEvent.filename </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -// The worker events races with the window's load event; if the worker events -// arrive first, the harness will detect the error event and fail the test. -setup({ allow_uncaught_exception: true }); - -async_test(function(t) { - var worker = new Worker('./support/ErrorEvent.js'); - worker.onerror = t.step_func_done(function(e) { - var href = location.href; - var expected = href.substring(0, href.lastIndexOf('/')) + '/support/ErrorEvent.js'; - assert_equals(e.filename, expected); - }); - worker.postMessage("Error Message"); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_lineno.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_lineno.htm deleted file mode 100644 index ad98172..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_lineno.htm +++ /dev/null
@@ -1,18 +0,0 @@ -<!DOCTYPE html> -<title> AbstractWorker ErrorEvent.lineno </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -// The worker events races with the window's load event; if the worker events -// arrive first, the harness will detect the error event and fail the test. -setup({ allow_uncaught_exception: true }); - -async_test(function(t) { - var worker = new Worker('./support/ErrorEvent.js'); - worker.onerror = t.step_func_done(function(e) { - assert_equals(e.lineno, 3); - }); - worker.postMessage("Error Message"); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_message.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_message.htm deleted file mode 100644 index 5602d9bc..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_message.htm +++ /dev/null
@@ -1,19 +0,0 @@ -<!DOCTYPE html> -<title> AbstractWorker ErrorEvent.message </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -// The worker events races with the window's load event; if the worker events -// arrive first, the harness will detect the error event and fail the test. -setup({ allow_uncaught_exception: true }); - -async_test(function(t) { - var message = 'Error Message'; - var worker = new Worker('./support/ErrorEvent.js'); - worker.onerror = t.step_func_done(function(e) { - assert_greater_than(e.message.indexOf(message), -1); - }); - worker.postMessage(message); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_type.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_type.htm deleted file mode 100644 index 3a0f85ad..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_type.htm +++ /dev/null
@@ -1,19 +0,0 @@ -<!DOCTYPE html> -<title> AbstractWorker ErrorEvent.type </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -// The worker events races with the window's load event; if the worker events -// arrive first, the harness will detect the error event and fail the test. -setup({ allow_uncaught_exception: true }); - -async_test(function(t) { - var worker = new Worker('./support/ErrorEvent.js'); - worker.onerror = t.step_func_done(function(e) { - assert_class_string(e, 'ErrorEvent'); - assert_equals(e.type, 'error'); - }); - worker.postMessage("Error Message"); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_basic.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_basic.htm deleted file mode 100644 index d2b57b4..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_basic.htm +++ /dev/null
@@ -1,31 +0,0 @@ -<!DOCTYPE html> -<title> Web Workers Basic Tests </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -function create_worker() { - return new Worker('./support/WorkerBasic.js'); -} - -test(function() { - var worker = create_worker(); - assert_class_string(worker, "Worker"); -}, "Worker constructor"); - -async_test(function(t) { - var worker = create_worker(); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data, "Pass"); - }); - worker.postMessage("start"); -}, "MessageEvent.data"); - -async_test(function(t) { - var worker = create_worker(); - worker.addEventListener("message", t.step_func_done(function(e) { - assert_equals(e.type, "message"); - }), true); - worker.postMessage("start"); -}, "MessageEvent.type"); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_cross_origin_security_err.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_cross_origin_security_err.htm deleted file mode 100644 index 647a8b81..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_cross_origin_security_err.htm +++ /dev/null
@@ -1,17 +0,0 @@ -<!DOCTYPE html> -<title> Worker cross-origin URL </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - try { - var w = new Worker("ftp://example.org/support/WorkerBasic.js"); - w.onerror = t.step_func_done(function(e) { - assert_true(e instanceof ErrorEvent); - }); - } catch (e) { - t.step_func_done(function(e) { assert_true(true); }); - } -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_dispatchEvent_ErrorEvent.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_dispatchEvent_ErrorEvent.htm deleted file mode 100644 index aea7e025..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_dispatchEvent_ErrorEvent.htm +++ /dev/null
@@ -1,37 +0,0 @@ -<!DOCTYPE html> -<title> ErrorEvent and Worker.dispatchEvent() </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var event = "error"; - var filename = './support/ErrorEvent.js'; - var message = 'Hello Worker'; - var lineno = 5; - var colno = 6; - var error = new Error("test"); - var worker = new Worker(filename); - worker.addEventListener(event, t.step_func_done(function(e) { - assert_equals(e.type, event, 'type'); - assert_equals(e.message, message, 'message'); - assert_equals(e.filename, filename, 'filename'); - assert_equals(e.lineno, lineno, 'lineno'); - assert_equals(e.colno, colno, 'colno'); - assert_equals(e.error, error, 'error'); - }), true); - var e = new ErrorEvent(event, {bubbles:true, cancelable:true, message:message, filename:filename, lineno:lineno, colno:colno, error:error}); - worker.dispatchEvent(e); -}); - -test(function() { - var e = document.createEvent("ErrorEvent"); - var eProto = Object.getPrototypeOf(e); - assert_equals(eProto, ErrorEvent.prototype); -}, "document.createEvent('ErrorEvent')"); - -test(function() { - var e = new ErrorEvent("error"); - assert_false("initErrorEvent" in e, "should not be supported"); -}, "initErrorEvent"); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_script_mimetype.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_script_mimetype.htm deleted file mode 100644 index 04fe68e..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_script_mimetype.htm +++ /dev/null
@@ -1,14 +0,0 @@ -<!DOCTYPE html> -<title> Worker constructor with script inside text file </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker('./support/WorkerText.txt'); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data, "Pass"); - }); - worker.postMessage("start"); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_terminate_event_queue.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_terminate_event_queue.htm deleted file mode 100644 index 5d9472a..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_terminate_event_queue.htm +++ /dev/null
@@ -1,22 +0,0 @@ -<!DOCTYPE html> -<title> AbstractWorker terminate(): clear event queue </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var testResult; - var worker = new Worker('./support/WorkerTerminate.js'); - worker.onmessage = this.step_func(function(e) { - testResult = e.data; - if (testResult >= 10000) { - worker.terminate(); - worker.onmessage = this.unreached_func('Unexpected message event'); - setTimeout(this.step_func_done(function() { - assert_equals(testResult, 10000); - }), 100); - } - }); - worker.postMessage("ping"); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/importScripts.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/importScripts.html deleted file mode 100644 index 0fbd35b..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/importScripts.html +++ /dev/null
@@ -1,14 +0,0 @@ -<!doctype html> -<meta charset=utf-8> -<title>Base URL in workers: importScripts</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script> -async_test(function() { - var worker = new Worker("../beta/importScripts.py"); - worker.onmessage = this.step_func_done(function(e) { - assert_equals(e.data, "gamma"); - }); - worker.onerror = this.unreached_func("Got error event"); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/sharedworker.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/sharedworker.html deleted file mode 100644 index 25d25823..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/sharedworker.html +++ /dev/null
@@ -1,14 +0,0 @@ -<!doctype html> -<meta charset=utf-8> -<title>Base URL in workers: new SharedWorker()</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script> -async_test(function() { - var worker = new Worker("../beta/sharedworker.py"); - worker.onmessage = this.step_func_done(function(e) { - assert_equals(e.data, "gamma"); - }); - worker.onerror = this.unreached_func("Got error event"); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/worker.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/worker.html deleted file mode 100644 index 284425e..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/worker.html +++ /dev/null
@@ -1,14 +0,0 @@ -<!doctype html> -<meta charset=utf-8> -<title>Base URL in workers: new Worker()</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script> -async_test(function() { - var worker = new Worker("../beta/worker.py"); - worker.onmessage = this.step_func_done(function(e) { - assert_equals(e.data, "gamma"); - }); - worker.onerror = this.unreached_func("Got error event"); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/xhr.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/xhr.html deleted file mode 100644 index 9a1219b4..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/xhr.html +++ /dev/null
@@ -1,14 +0,0 @@ -<!doctype html> -<meta charset=utf-8> -<title>Base URL in workers: XHR</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script> -async_test(function() { - var worker = new Worker("../beta/xhr.py"); - worker.onmessage = this.step_func_done(function(e) { - assert_equals(e.data, "gamma\n"); - }); - worker.onerror = this.unreached_func("Got error event"); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/importScripts.py b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/importScripts.py deleted file mode 100644 index 75dac19..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/importScripts.py +++ /dev/null
@@ -1,3 +0,0 @@ -def main(request, response): - return (302, "Moved"), [("Location", "../gamma/importScripts.js")], "postMessage('executed redirecting script');" -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/script.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/script.js deleted file mode 100644 index 8fe3dfc..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/script.js +++ /dev/null
@@ -1 +0,0 @@ -postMessage('beta');
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/sharedworker.py b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/sharedworker.py deleted file mode 100644 index 875cc9a..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/sharedworker.py +++ /dev/null
@@ -1,3 +0,0 @@ -def main(request, response): - return (302, "Moved"), [("Location", "../gamma/sharedworker.js")], "postMessage('executed redirecting script');" -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/subsharedworker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/subsharedworker.js deleted file mode 100644 index de6a8ca..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/subsharedworker.js +++ /dev/null
@@ -1,3 +0,0 @@ -onconnect = function(e) { - e.source.postMessage('beta'); -}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/subworker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/subworker.js deleted file mode 100644 index 997cecd..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/subworker.js +++ /dev/null
@@ -1 +0,0 @@ -postMessage("beta");
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/test.txt b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/test.txt deleted file mode 100644 index 65b2df87..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/test.txt +++ /dev/null
@@ -1 +0,0 @@ -beta
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/worker.py b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/worker.py deleted file mode 100644 index 44baf520..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/worker.py +++ /dev/null
@@ -1,3 +0,0 @@ -def main(request, response): - return (302, "Moved"), [("Location", "../gamma/worker.js")], "postMessage('executed redirecting script');" -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/xhr.py b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/xhr.py deleted file mode 100644 index de3f04e..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/xhr.py +++ /dev/null
@@ -1,3 +0,0 @@ -def main(request, response): - return (302, "Moved"), [("Location", "../gamma/xhr.js")], "postMessage('executed redirecting script');" -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/importScripts.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/importScripts.js deleted file mode 100644 index 3f76856..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/importScripts.js +++ /dev/null
@@ -1 +0,0 @@ -importScripts("script.js");
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/script.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/script.js deleted file mode 100644 index dddf224..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/script.js +++ /dev/null
@@ -1 +0,0 @@ -postMessage('gamma');
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/sharedworker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/sharedworker.js deleted file mode 100644 index d0718cfd..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/sharedworker.js +++ /dev/null
@@ -1,4 +0,0 @@ -var worker = new SharedWorker("subsharedworker.js"); -worker.port.onmessage = function(e) { - postMessage(e.data); -}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/subsharedworker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/subsharedworker.js deleted file mode 100644 index e23602f..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/subsharedworker.js +++ /dev/null
@@ -1,3 +0,0 @@ -onconnect = function(e) { - e.source.postMessage('gamma'); -}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/subworker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/subworker.js deleted file mode 100644 index 44407358..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/subworker.js +++ /dev/null
@@ -1 +0,0 @@ -postMessage("gamma");
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/test.txt b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/test.txt deleted file mode 100644 index af17f6c..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/test.txt +++ /dev/null
@@ -1 +0,0 @@ -gamma
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/worker.js deleted file mode 100644 index 8cfbcae..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/worker.js +++ /dev/null
@@ -1,4 +0,0 @@ -var worker = new Worker("subworker.js"); -worker.onmessage = function(e) { - postMessage(e.data); -}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/xhr.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/xhr.js deleted file mode 100644 index 70f3315..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/xhr.js +++ /dev/null
@@ -1,4 +0,0 @@ -var x = new XMLHttpRequest(); -x.open("GET", "test.txt", false); -x.send(); -postMessage(x.response);
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/1 b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/1 deleted file mode 100644 index c3f67be..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/1 +++ /dev/null
@@ -1,3 +0,0 @@ -onconnect = function(e) { - e.ports[0].postMessage(['1', self.name]); -} \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/URLMismatchError.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/URLMismatchError.htm deleted file mode 100644 index e74e660..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/URLMismatchError.htm +++ /dev/null
@@ -1,19 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>Web Workers: SharedWorker - throw URLMismatchError</title> -<link rel="author" title="Intel" href="http://www.intel.com"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> - - test(function() { - var worker = new SharedWorker('shared-worker.js', 'name'); - - assert_throws("URLMismatchError", function() { - new SharedWorker('some-other-url.js', 'name'); - }); - - }, "Create SharedWorker with different URLs but same name"); - -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/connect-event.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/connect-event.html deleted file mode 100644 index a9719d9..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/connect-event.html +++ /dev/null
@@ -1,26 +0,0 @@ -<!-- -onconnect = function(e) { - e.ports[0].postMessage([e.data === '', e instanceof MessageEvent, e.ports.length == 1]); -}; -/* ---> -<!doctype html> -<title>connect event</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -(async_test()).step(function() { - var worker = new SharedWorker('#'); - worker.port.addEventListener('message', this.step_func(function(e) { - assert_true(e.data[0], "e.data === ''"); - assert_true(e.data[1], "e instanceof MessageEvent"); - assert_true(e.data[2], "e.ports.length == 1"); - this.done(); - }), false); - worker.port.start(); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/dummy-name.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/dummy-name.html deleted file mode 100644 index 9e27329..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/dummy-name.html +++ /dev/null
@@ -1,17 +0,0 @@ -<!-- -/* ---> -<!doctype html> -<title>creating a dummy shared worker with name "foo"</title> -<link rel=help href="http://www.whatwg.org/html/#dom-sharedworker"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -test(function() { - var worker = new SharedWorker('#', 'foo'); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/dummy-shared-worker.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/dummy-shared-worker.html deleted file mode 100644 index e9aff9c5..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/dummy-shared-worker.html +++ /dev/null
@@ -1,17 +0,0 @@ -<!-- -/* ---> -<!doctype html> -<title>creating a dummy shared worker</title> -<link rel=help href="http://www.whatwg.org/html/#dom-sharedworker"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -test(function() { - var worker = new SharedWorker('#'); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/empty-name.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/empty-name.html deleted file mode 100644 index 95ff6d1..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/empty-name.html +++ /dev/null
@@ -1,17 +0,0 @@ -<!-- -/* ---> -<!doctype html> -<title>creating a dummy shared worker with explicit name ""</title> -<link rel=help href="http://www.whatwg.org/html/#dom-sharedworker"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -test(function() { - var worker = new SharedWorker('#', ''); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/global-members.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/global-members.html deleted file mode 100644 index af4eb1d..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/global-members.html +++ /dev/null
@@ -1,34 +0,0 @@ -<!-- -var expected = 'self location close onerror importScripts navigator addEventListener removeEventListener dispatchEvent name applicationCache onconnect setTimeout clearTimeout setInterval clearInterval'.split(' '); -var log = ''; -for (var i = 0; i < expected.length; ++i) { - if (!(expected[i] in self)) - log += expected[i] + ' did not exist\n'; -} -onconnect = function(e) { - e.ports[0].postMessage(log); -}; -/* ---> -<!doctype html> -<title>members of SharedWorkerGlobalScope</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -(async_test()).step(function() { - var worker = new SharedWorker('#'); - worker.port.addEventListener('message', this.step_func(function(e) { - assert_equals(e.data, ''); - this.done(); - }), false); - worker.port.start(); -}); -</script> -<!-- -*/ -//--> - - - -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/interface-objects.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/interface-objects.html deleted file mode 100644 index e91b2dc6..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/interface-objects.html +++ /dev/null
@@ -1,41 +0,0 @@ -<!-- -var prt; -function handleCall(e) { - var log = []; - for (var i = 0; i < e.data.length; ++i) { - if (!(e.data[i] in self)) - log.push(e.data[i]); - } - prt.postMessage('These were missing: '+log.join(', ')); -} -onconnect = function(e) { - prt = e.ports[0]; - prt.onmessage = handleCall; -}; -/* ---> -<!doctype html> -<title>expected interface objects/constructors</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -(async_test()).step(function() { - var expected = 'XMLHttpRequest WebSocket EventSource MessageChannel Worker SharedWorker ApplicationCache'.split(' '); - var supported = []; - for (var i = 0; i < expected.length; ++i) { - if (expected[i] in window) - supported.push(expected[i]); - } - var worker = new SharedWorker('#'); - worker.port.start(); - worker.port.postMessage(supported); - worker.port.addEventListener('message', this.step_func(function(e) { - assert_equals(e.data, ''); - this.done(); - }), false); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/name.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/name.html deleted file mode 100644 index 823e16c..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/name.html +++ /dev/null
@@ -1,24 +0,0 @@ -<!-- -onconnect = function(e) { - e.ports[0].postMessage(self.name); -} -/* ---> -<!doctype html> -<title>self.name</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -(async_test()).step(function() { - var worker = new SharedWorker('#', 'hello'); - worker.port.addEventListener('message', this.step_func(function(e) { - assert_equals(e.data, 'hello'); - this.done(); - }), false); - worker.port.start(); -}); -</script> -<!-- -*/ -//--> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/no-arguments-ctor.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/no-arguments-ctor.html deleted file mode 100644 index eaee870d..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/no-arguments-ctor.html +++ /dev/null
@@ -1,20 +0,0 @@ -<!-- -/* ---> -<!doctype html> -<title>no arguments</title> -<link rel=help href="http://www.whatwg.org/html/#sharedworker"> -<link rel=help href="http://dev.w3.org/2006/webapi/WebIDL/#es-interface-call"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -test(function() { - assert_throws(new TypeError(), function() { - var worker = new SharedWorker(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/null b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/null deleted file mode 100644 index 5c38505b..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/null +++ /dev/null
@@ -1,3 +0,0 @@ -onconnect = function(e) { - e.ports[0].postMessage(['null', self.name]); -} \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/null-arguments.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/null-arguments.html deleted file mode 100644 index c711b2c..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/null-arguments.html +++ /dev/null
@@ -1,25 +0,0 @@ -<!-- -onconnect = function(e) { - e.ports[0].postMessage(['FAIL', self.name]); -} -/* ---> -<!doctype html> -<title>null as arguments</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -(async_test()).step(function() { - var worker = new SharedWorker(null, null); - worker.port.addEventListener('message', this.step_func(function(e) { - assert_equals(e.data[0], 'null', 'first arg'); - assert_equals(e.data[1], 'null', 'second arg'); - this.done(); - }), false); - worker.port.start(); -}); -</script> -<!-- -*/ -//--> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/number-arguments.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/number-arguments.html deleted file mode 100644 index 1a4cfb2..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/number-arguments.html +++ /dev/null
@@ -1,25 +0,0 @@ -<!-- -onconnect = function(e) { - e.ports[0].postMessage(['FAIL', self.name]); -} -/* ---> -<!doctype html> -<title>1 as arguments</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -(async_test()).step(function() { - var worker = new SharedWorker(1, 1); - worker.port.addEventListener('message', this.step_func(function(e) { - assert_equals(e.data[0], '1', 'first arg'); - assert_equals(e.data[1], '1', 'second arg'); - this.done(); - }), false); - worker.port.start(); -}); -</script> -<!-- -*/ -//--> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/port-onmessage.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/port-onmessage.html deleted file mode 100644 index a2f4df0..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/port-onmessage.html +++ /dev/null
@@ -1,23 +0,0 @@ -<!-- -onconnect = function(e) { - e.ports[0].postMessage(true); -} -/* ---> -<!doctype html> -<title>worker.port.onmessage</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -(async_test()).step(function() { - var worker = new SharedWorker('#', ''); - worker.port.onmessage = this.step_func(function(e) { - assert_true(e.data); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/port-properties.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/port-properties.html deleted file mode 100644 index f8a676d..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/port-properties.html +++ /dev/null
@@ -1,26 +0,0 @@ -<!-- -/* ---> -<!doctype html> -<title>worker.port</title> -<link rel=help href="http://www.whatwg.org/html/#sharedworker"> -<link rel=help href="http://www.whatwg.org/html/#messageport"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -test(function() { - var worker = new SharedWorker('#', ''); - assert_true('port' in worker, "port"); - assert_true('postMessage' in worker.port, "postMessage"); - assert_true('start' in worker.port, "start"); - assert_true('close' in worker.port, "close"); - assert_true('onmessage' in worker.port, "onmessage"); - assert_true('addEventListener' in worker.port, "addEventListener"); - assert_true('removeEventListener' in worker.port, "removeEventListener"); - assert_true('dispatchEvent' in worker.port, "dispatchEvent"); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/port-readonly.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/port-readonly.html deleted file mode 100644 index f087ab0..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/port-readonly.html +++ /dev/null
@@ -1,21 +0,0 @@ -<!-- -/* ---> -<!doctype html> -<title>setting worker.port</title> -<link rel=help href="http://www.whatwg.org/html/#sharedworker"> -<link rel=help href="http://dev.w3.org/2006/webapi/WebIDL/#dfn-attribute-setter"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -test(function() { - var worker = new SharedWorker('#', ''); - var x = worker.port; - worker.port = 1; - assert_equals(worker.port, x); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/same-origin.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/same-origin.html deleted file mode 100644 index 2e0dd8d..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/same-origin.html +++ /dev/null
@@ -1,67 +0,0 @@ -<!-- -/* ---> -<!doctype html> -<title>same-origin checks</title> -<link rel=help href="http://www.whatwg.org/html/#dom-sharedworker"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -// Needed to prevent a race condition if a worker throws an exception that may or may -// not propogate to the window before the tests finish -setup({allow_uncaught_exception: true}); - -function testSharedWorkerHelper(t, script) { - try { - var worker = new SharedWorker(script, ''); - worker.onerror = t.step_func_done(function(e) { - assert_true(e instanceof ErrorEvent); - }); - } catch (e) { - t.step_func_done(function(e) { assert_true(true); }); - } -} - -test(function() { - assert_throws("SecurityError", function() { new SharedWorker('unsupported:', ''); }); -}, "unsupported_scheme"); - -async_test(function() { - var worker = new SharedWorker('data:,onconnect = function(e) { e.ports[0].postMessage(1); }', ''); - worker.port.onmessage = this.step_func_done(function(e) { - assert_equals(e.data, 1); - }); -}, "data_url"); - -async_test(function(t) { - testSharedWorkerHelper(this, 'javascript:""'); -}, "javascript_url"); - -async_test(function(t) { - testSharedWorkerHelper(this, 'about:blank'); -}, "about_blank"); - -async_test(function(t) { - testSharedWorkerHelper(this, 'http://www.opera.com/'); -}, "opera_com"); - -async_test(function(t) { - testSharedWorkerHelper(this, location.protocol+'//'+location.hostname+':81/'); -}, "port_81"); - -async_test(function(t) { - testSharedWorkerHelper(this, 'https://'+location.hostname+':80/'); -}, "https_port_80"); - -async_test(function(t) { - testSharedWorkerHelper(this, 'https://'+location.hostname+':8000/'); -}, "https_port_8000"); - -async_test(function(t) { - testSharedWorkerHelper(this, 'http://'+location.hostname+':8012/'); -}, "http_port_8012"); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/setting-port-members.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/setting-port-members.html deleted file mode 100644 index 8c79ff2..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/setting-port-members.html +++ /dev/null
@@ -1,59 +0,0 @@ -<!-- -/* ---> -<!doctype html> -<title>setting members of worker.port</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -setup(function() { - window.worker = new SharedWorker('#', ''); -}); -test(function() { - worker.port.postMessage = 1; - assert_equals(worker.port.postMessage, 1); -}, 'postMessage'); -test(function() { - worker.port.start = 1; - assert_equals(worker.port.start, 1); -}, 'start'); -test(function() { - worker.port.close = 1; - assert_equals(worker.port.close, 1); -}, 'close'); -test(function() { - var f = function(){}; - worker.port.onmessage = f; - assert_equals(worker.port.onmessage, f, 'function(){}'); - worker.port.onmessage = 1; - assert_equals(worker.port.onmessage, null, '1'); - worker.port.onmessage = f; - worker.port.onmessage = ';'; - assert_equals(worker.port.onmessage, null, '";"'); - worker.port.onmessage = f; - worker.port.onmessage = {handleEvent:function(){}}; - assert_equals(worker.port.onmessage, null, '{handleEvent:function(){}}'); - worker.port.onmessage = f; - worker.port.onmessage = null; - assert_equals(worker.port.onmessage, null, 'null'); - worker.port.onmessage = f; - worker.port.onmessage = undefined; - assert_equals(worker.port.onmessage, null, 'undefined'); -}, 'onmessage'); -test(function() { - worker.port.addEventListener = 1; - assert_equals(worker.port.addEventListener, 1); -}, 'addEventListener'); -test(function() { - worker.port.removeEventListener = 1; - assert_equals(worker.port.removeEventListener, 1); -}, 'removeEventListener'); -test(function() { - worker.port.despatchEvent = 1; - assert_equals(worker.port.despatchEvent, 1); -}, 'despatchEvent'); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/shared-worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/shared-worker.js deleted file mode 100644 index babebb1..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/shared-worker.js +++ /dev/null
@@ -1,6 +0,0 @@ -onconnect = function(e) { - var port = e.ports[0]; - port.onmessage = function(e) { - port.postMessage('ping'); - } -}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/undefined b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/undefined deleted file mode 100644 index 3fe840d..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/undefined +++ /dev/null
@@ -1,3 +0,0 @@ -onconnect = function(e) { - e.ports[0].postMessage(['undefined', self.name]); -} \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/undefined-arguments.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/undefined-arguments.html deleted file mode 100644 index b9a3b369..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/undefined-arguments.html +++ /dev/null
@@ -1,25 +0,0 @@ -<!-- -onconnect = function(e) { - e.ports[0].postMessage(['FAIL', self.name]); -} -/* ---> -<!doctype html> -<title>undefined as arguments</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -(async_test()).step(function() { - var worker = new SharedWorker(undefined, undefined); - worker.port.addEventListener('message', this.step_func(function(e) { - assert_equals(e.data[0], 'undefined', 'first arg'); - assert_equals(e.data[1], 'undefined', 'second arg'); - this.done(); - }), false); - worker.port.start(); -}); -</script> -<!-- -*/ -//--> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/unexpected-global-properties.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/unexpected-global-properties.html deleted file mode 100644 index 39739022..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/unexpected-global-properties.html +++ /dev/null
@@ -1,30 +0,0 @@ -<!-- -var unexpected = 'open print stop getComputedStyle getSelection releaseEvents captureEvents alert confirm prompt addEventStream removeEventStream back forward attachEvent detachEvent navigate DOMParser XMLSerializer XPathEvaluator XSLTProcessor opera Image Option frames Audio SVGUnitTypes SVGZoomAndPan java netscape sun Packages ByteArray closed defaultStatus document event frameElement history innerHeight innerWidth opener outerHeight outerWidth pageXOffset pageYOffset parent screen screenLeft screenTop screenX screenY status top window length'.split(' '); // iterated window in opera and removed expected ones -var log = ''; -for (var i = 0; i < unexpected.length; ++i) { - if (unexpected[i] in self) - log += unexpected[i] + ' '; -} -onconnect = function(e) { - e.ports[0].postMessage(log); -}; -/* ---> -<!doctype html> -<title>unexpected members/interface objects/constructors</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -(async_test()).step(function() { - var worker = new SharedWorker('#'); - worker.port.addEventListener('message', this.step_func(function(e) { - assert_equals(e.data, ''); - this.done(); - }), false); - worker.port.start(); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/unresolvable-url.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/unresolvable-url.html deleted file mode 100644 index 2ca3d93d..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/unresolvable-url.html +++ /dev/null
@@ -1,19 +0,0 @@ -<!-- -/* ---> -<!doctype html> -<title>resolving broken url</title> -<link rel=help href="http://www.whatwg.org/html/#dom-sharedworker"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -test(function() { - assert_throws("SyntaxError", function() { - var worker = new SharedWorker('http://foo bar'); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/1 b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/1 deleted file mode 100644 index ea0b7c8f..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/1 +++ /dev/null
@@ -1 +0,0 @@ -postMessage('1');
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/AbstractWorker.onerror.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/AbstractWorker.onerror.html deleted file mode 100644 index c40424d..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/AbstractWorker.onerror.html +++ /dev/null
@@ -1,48 +0,0 @@ -<!-- -for (;) // should cause onerror to be invoked, but onerror is null, so - // the error is "not handled". should fire an ErrorEvent on the - // worker. - break; -postMessage(1); // shouldn't do anything since the script doesn't compile -/* ---> -<!doctype html> -<title>AbstractWorker.onerror</title> -<link rel=help href="https://html.spec.whatwg.org/multipage/#runtime-script-errors-2"> -<link rel=help href="https://html.spec.whatwg.org/multipage/#report-the-error"> -<link rel=help href="https://html.spec.whatwg.org/multipage/#the-event-handler-processing-algorithm"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -setup({allow_uncaught_exception:true}); -async_test(function() { - var worker = new Worker('#'); - var error; - worker.onerror = this.step_func(function(a, b, c) { - error = a; - assert_equals('' + a, '[object ErrorEvent]'); - assert_true("message" in a, 'ErrorEvent.message'); - assert_equals(typeof a.message, "string", 'ErrorEvent.message'); - assert_equals(a.filename, document.URL + '#', 'ErrorEvent.filename'); - assert_true("lineno" in a, 'ErrorEvent.lineno'); - assert_equals(typeof a.lineno, "number", 'ErrorEvent.lineno'); - assert_equals(b, undefined, 'unexpected second argument to onerror'); - assert_equals(c, undefined, 'unexpected third argument to onerror'); - }); - worker.onmessage = this.step_func(function(e) { - assert_unreached('onmessage was invoked but worker script shouldn\'t have compiled'); - }); - window.onerror = this.step_func_done(function(a, b, c, d, e, f) { - assert_equals(a, error.message, 'message'); - assert_equals(b, error.filename, 'filename'); - assert_equals(c, error.lineno, 'lineno'); - assert_equals(d, error.colno, 'colno'); - assert_equals(e, error.error, 'error'); - assert_equals(f, undefined, 'unexpected sixth argument to onerror'); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/Blob-url.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/Blob-url.html deleted file mode 100644 index 168fc91..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/Blob-url.html +++ /dev/null
@@ -1,21 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>Web Workers: Worker - Blob url</title> -<link rel="author" title="Intel" href="http://www.intel.com"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> - - async_test(function(t) { - var blob = new Blob(["onmessage = function(event) { postMessage(event.data); }"], {type: "text/plain"}); - var worker = new Worker(window.URL.createObjectURL(blob)); - var data = "Blob URL"; - worker.postMessage(data); - worker.onmessage = t.step_func(function(event) { - assert_equals(event.data, data, "event.data"); - t.done(); - }); - }, "Worker supports Blob url"); - -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/DedicatedWorkerGlobalScope-members.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/DedicatedWorkerGlobalScope-members.worker.js deleted file mode 100644 index 2ef466c..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/DedicatedWorkerGlobalScope-members.worker.js +++ /dev/null
@@ -1,18 +0,0 @@ -importScripts("/resources/testharness.js"); - -var expected = [ - 'postMessage', 'onmessage', /* DedicatedWorkerGlobalScope */ - 'self', 'location', 'close', 'onerror', 'onoffline', 'ononline', /* WorkerGlobalScope */ - 'addEventListener', 'removeEventListener', 'dispatchEvent', /* EventListener */ - 'importScripts', 'navigator', /* WorkerUtils */ - 'setTimeout', 'clearTimeout', 'setInterval', 'clearInterval', /* WindowTimers */ - 'btoa', 'atob' /* WindowBase64 */ -]; -for (var i = 0; i < expected.length; ++i) { - var property = expected[i]; - test(function() { - assert_true(property in self); - }, "existence of " + property); -} - -done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/ctor-1.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/ctor-1.html deleted file mode 100644 index bd865261..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/ctor-1.html +++ /dev/null
@@ -1,23 +0,0 @@ -<!-- -postMessage('FAIL'); -/* ---> -<!doctype html> -<title>1 as argument</title> -<link rel=help href="http://www.whatwg.org/html/#dom-worker"> -<link rel=help href="http://dev.w3.org/2006/webapi/WebIDL/#es-DOMString"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -var t = async_test(); -t.step(function() { - var worker = new Worker(1); - worker.addEventListener('message', t.step_func_done(function(e) { - assert_equals(e.data, '1') - }), false); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/ctor-null.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/ctor-null.html deleted file mode 100644 index 94ab71a..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/ctor-null.html +++ /dev/null
@@ -1,23 +0,0 @@ -<!-- -postMessage('FAIL'); -/* ---> -<!doctype html> -<title>null as argument</title> -<link rel=help href="http://www.whatwg.org/html/#dom-worker"> -<link rel=help href="http://dev.w3.org/2006/webapi/WebIDL/#es-DOMString"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -var t = async_test(); -t.step(function() { - var worker = new Worker(null); - worker.addEventListener('message', t.step_func_done(function(e) { - assert_equals(e.data, 'null') - }), false); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/ctor-undefined.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/ctor-undefined.html deleted file mode 100644 index 2d9eb6e6..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/ctor-undefined.html +++ /dev/null
@@ -1,23 +0,0 @@ -<!-- -postMessage('FAIL'); -/* ---> -<!doctype html> -<title>undefined as argument</title> -<link rel=help href="http://www.whatwg.org/html/#dom-worker"> -<link rel=help href="http://dev.w3.org/2006/webapi/WebIDL/#es-DOMString"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -var t = async_test(); -t.step(function() { - var worker = new Worker(undefined); - worker.addEventListener('message', t.step_func_done(function(e) { - assert_equals(e.data, 'undefined') - }), false); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/expected-self-properties.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/expected-self-properties.worker.js deleted file mode 100644 index 0ce41b59..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/expected-self-properties.worker.js +++ /dev/null
@@ -1,11 +0,0 @@ -importScripts("/resources/testharness.js"); - -var expected = ['XMLHttpRequest', 'WebSocket', 'EventSource', 'MessageChannel', 'Worker', 'SharedWorker']; -for (var i = 0; i < expected.length; ++i) { - var property = expected[i]; - test(function() { - assert_true(property in self); - }, "existence of " + property); -} - -done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/no-arguments-ctor.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/no-arguments-ctor.html deleted file mode 100644 index 770c7cc..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/no-arguments-ctor.html +++ /dev/null
@@ -1,13 +0,0 @@ -<!doctype html> -<meta charset=utf-8> -<title>without arguments</title> -<link rel=help href="http://dev.w3.org/2006/webapi/WebIDL/#es-interface-call"> -<link rel=help href="http://www.whatwg.org/html/#dedicated-workers-and-the-worker-interface"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -test(function() { - assert_throws(new TypeError(), function() { new Worker(); }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/null b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/null deleted file mode 100644 index 6d079b5..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/null +++ /dev/null
@@ -1 +0,0 @@ -postMessage('null');
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/resolve-empty-string.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/resolve-empty-string.html deleted file mode 100644 index 0426223..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/resolve-empty-string.html +++ /dev/null
@@ -1,22 +0,0 @@ -<!-- -postMessage('ok'); -/* ---> -<!doctype html> -<meta charset=utf-8> -<title>resolve the empty string</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -var t = async_test(); -t.step(function() { - var worker = new Worker(''); - worker.addEventListener('message', t.step_func_done(function(e) { - assert_equals(e.data, 'ok'); - }), false); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/same-origin.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/same-origin.html deleted file mode 100644 index 9b0148d..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/same-origin.html +++ /dev/null
@@ -1,63 +0,0 @@ -<!doctype html> -<meta charset=utf-8> -<title>same-origin checks; the script is in a script element</title> -<link rel=help href="http://www.whatwg.org/html/#dom-worker"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -// Needed to prevent a race condition if a worker throws an exception that may or may -// not propogate to the window before the tests finish -setup({allow_uncaught_exception: true}); - -function testSharedWorkerHelper(t, script) { - try { - var worker = new SharedWorker(script, ''); - worker.onerror = t.step_func_done(function(e) { - assert_true(e instanceof ErrorEvent); - }); - } catch (e) { - t.step_func_done(function(e) { assert_true(true); }); - } -} - -test(function() { - assert_throws("SecurityError", function() { new Worker('unsupported:'); }); -}, "unsupported_scheme"); - -async_test(function() { - var worker = new Worker('data:,postMessage(1);'); - worker.onmessage = this.step_func_done(function(e) { - assert_equals(e.data, 1); - }); -}, "data_url"); - -async_test(function(t) { - testSharedWorkerHelper(t, 'about:blank'); -}, "about_blank"); - -async_test(function(t) { - testSharedWorkerHelper(t, 'http://www.example.invalid/'); -}, "example_invalid"); - -async_test(function(t) { - testSharedWorkerHelper(t, location.protocol+'//'+location.hostname+':81/'); -}, "port_81"); - -async_test(function(t) { - testSharedWorkerHelper(t, 'https://'+location.hostname+':80/'); -}, "https_port_80"); - -async_test(function(t) { - testSharedWorkerHelper(t, 'https://'+location.hostname+':8000/'); -}, "https_port_8000"); - -async_test(function(t) { - testSharedWorkerHelper(t, 'http://'+location.hostname+':8012/'); -}, "http_post_8012"); - -async_test(function(t) { - testSharedWorkerHelper(t,'javascript:""'); -}, "javascript_url"); - -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/sample_worker/worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/sample_worker/worker.js deleted file mode 100644 index 19bbea58..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/sample_worker/worker.js +++ /dev/null
@@ -1 +0,0 @@ -onmessage = function(event) { postMessage(event.data); }
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/terminate.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/terminate.html deleted file mode 100644 index 52f9707d..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/terminate.html +++ /dev/null
@@ -1,44 +0,0 @@ -<!-- -(function f() { - postMessage(1); - setTimeout(f, 0); -})(); -/* ---> -<!doctype html> -<title>terminate()</title> -<link rel=help href="http://www.whatwg.org/html/#dom-worker-terminate"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -var t = async_test(); -t.step(function() { - var worker = new Worker('#'); - var i = 0; - var expected; - - worker.onmessage = t.step_func(function() { - i++; - }); - - setTimeout(t.step_func(function() { - expected = i; - start_time = Date.now(); - //Hang the main thread for a bit to give the worker the chance to post some more messages - while(Date.now() - start_time < 500) { - //pass - } - worker.terminate(); - - setTimeout(t.step_func(function() { - assert_equals(i, expected); - t.done(); - }), 100); - - }), 100); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/undefined b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/undefined deleted file mode 100644 index bc7f482..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/undefined +++ /dev/null
@@ -1 +0,0 @@ -postMessage('undefined');
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/unexpected-self-properties.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/unexpected-self-properties.worker.js deleted file mode 100644 index aba85011..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/unexpected-self-properties.worker.js +++ /dev/null
@@ -1,11 +0,0 @@ -importScripts("/resources/testharness.js"); - -var unexpected = ['open', 'print', 'stop', 'getComputedStyle', 'getSelection', 'releaseEvents', 'captureEvents', 'alert', 'confirm', 'prompt', 'addEventStream', 'removeEventStream', 'back', 'forward', 'attachEvent', 'detachEvent', 'navigate', 'DOMParser', 'XMLSerializer', 'XPathEvaluator', 'XSLTProcessor', 'opera', 'Image', 'Option', 'frames', 'Audio', 'SVGUnitTypes', 'SVGZoomAndPan', 'java', 'netscape', 'sun', 'Packages', 'ByteArray', 'closed', 'defaultStatus', 'document', 'event', 'frameElement', 'history', 'innerHeight', 'innerWidth', 'name', 'opener', 'outerHeight', 'outerWidth', 'pageXOffset', 'pageYOffset', 'parent', 'screen', 'screenLeft', 'screenTop', 'screenX', 'screenY', 'status', 'top', 'window', 'length']; // iterated window in opera and removed expected ones -for (var i = 0; i < unexpected.length; ++i) { - var property = unexpected[i]; - test(function() { - assert_false(property in self); - }, "existence of " + property); -} - -done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/unresolvable-url.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/unresolvable-url.html deleted file mode 100644 index 8c04b00..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/unresolvable-url.html +++ /dev/null
@@ -1,12 +0,0 @@ -<!doctype html> -<meta charset=utf-8> -<title>unresolvable url</title> -<link rel=help href="http://www.whatwg.org/html/#dom-worker"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -test(function() { - assert_throws("SyntaxError", function() { new Worker('http://invalid url/'); }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/use-base-url.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/use-base-url.html deleted file mode 100644 index 94ce2a7..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/use-base-url.html +++ /dev/null
@@ -1,18 +0,0 @@ -<!doctype html> -<meta charset="utf-8"> -<title>Use the document base url when resolving worker URLs</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> - -<base href="/workers/constructors/Worker/sample_worker/"> -<script> - async_test(function(t) { - var worker = new Worker('worker.js'); - var data = "foo"; - worker.postMessage(data); - worker.onmessage = t.step_func_done(function(event) { - assert_equals(event.data, data, "event.data does not match expected data"); - }); - worker.onerror = t.unreached_func("received error event"); - }, "Use the document base url when resolving worker URLs"); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/data-url-shared.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/data-url-shared.html deleted file mode 100644 index 64aacf2..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/data-url-shared.html +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title>data URL shared worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(t => { - var worker = new SharedWorker("data:,onconnect = (e) => { fetch('/').then(() => e.ports[0].postMessage('fail'), () => e.ports[0].postMessage('pass')) }") // not same-origin - worker.port.onmessage = t.step_func_done(e => { - assert_equals(e.data, "pass") - }) -}) -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/data-url.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/data-url.html deleted file mode 100644 index c212a69..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/data-url.html +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title>data URL worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(t => { - var worker = new Worker("data:,fetch('/').then(() => self.postMessage('fail'), () => self.postMessage('pass'))") // not same-origin - worker.onmessage = t.step_func_done(e => { - assert_equals(e.data, "pass") - }) -}) -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces.idl b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces.idl deleted file mode 100644 index 228efba..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces.idl +++ /dev/null
@@ -1,106 +0,0 @@ -// ----------------------------------------------------------------------------- -// DOM -// ----------------------------------------------------------------------------- -[Exposed=(Window,Worker)] -interface EventTarget { - void addEventListener(DOMString type, EventListener? callback, optional boolean capture = false); - void removeEventListener(DOMString type, EventListener? callback, optional boolean capture = false); - boolean dispatchEvent(Event event); -}; - -callback interface EventListener { - void handleEvent(Event event); -}; - -// ----------------------------------------------------------------------------- -// HTML -// ----------------------------------------------------------------------------- -[TreatNonCallableAsNull] -callback EventHandlerNonNull = any (Event event); -typedef EventHandlerNonNull? EventHandler; - -[TreatNonCallableAsNull] -callback OnErrorEventHandlerNonNull = any ((Event or DOMString) event, optional DOMString source, optional unsigned long lineno, optional unsigned long column, optional any error); -typedef OnErrorEventHandlerNonNull? OnErrorEventHandler; - -[Exposed=Worker] -interface WorkerGlobalScope : EventTarget { - readonly attribute WorkerGlobalScope self; - readonly attribute WorkerLocation location; - - void close(); - attribute OnErrorEventHandler onerror; - attribute EventHandler onlanguagechange; - attribute EventHandler onoffline; - attribute EventHandler ononline; -}; - -[Global=(Worker,DedicatedWorker),Exposed=DedicatedWorker] -/*sealed*/ interface DedicatedWorkerGlobalScope : WorkerGlobalScope { - void postMessage(any message, optional sequence<Transferable> transfer); - attribute EventHandler onmessage; -}; - -//[Exposed=Worker] -partial interface WorkerGlobalScope { // not obsolete - void importScripts(DOMString... urls); - readonly attribute WorkerNavigator navigator; -}; -WorkerGlobalScope implements WindowTimers; -WorkerGlobalScope implements WindowBase64; - -[NoInterfaceObject, Exposed=(Window,Worker)] -interface WindowTimers { - long setTimeout(Function handler, optional long timeout = 0, any... arguments); - long setTimeout(DOMString handler, optional long timeout = 0, any... arguments); - void clearTimeout(optional long handle = 0); - long setInterval(Function handler, optional long timeout = 0, any... arguments); - long setInterval(DOMString handler, optional long timeout = 0, any... arguments); - void clearInterval(optional long handle = 0); -}; - -[NoInterfaceObject, Exposed=(Window,Worker)] -interface WindowBase64 { - DOMString btoa(DOMString btoa); - DOMString atob(DOMString atob); -}; - -[Exposed=Worker] -interface WorkerNavigator {}; -WorkerNavigator implements NavigatorID; -WorkerNavigator implements NavigatorLanguage; -WorkerNavigator implements NavigatorOnLine; - -[NoInterfaceObject, Exposed=(Window,Worker)] -interface NavigatorID { - readonly attribute DOMString appCodeName; // constant "Mozilla" - readonly attribute DOMString appName; - readonly attribute DOMString appVersion; - readonly attribute DOMString platform; - readonly attribute DOMString product; // constant "Gecko" - readonly attribute DOMString userAgent; -}; - -[NoInterfaceObject, Exposed=(Window,Worker)] -interface NavigatorLanguage { - readonly attribute DOMString? language; - readonly attribute DOMString[] languages; -}; - -[NoInterfaceObject, Exposed=(Window,Worker)] -interface NavigatorOnLine { - readonly attribute boolean onLine; -}; - -[Exposed=Worker] -interface WorkerLocation { - stringifier readonly attribute USVString href; - readonly attribute USVString origin; - readonly attribute USVString protocol; - readonly attribute USVString host; - readonly attribute USVString hostname; - readonly attribute USVString port; - readonly attribute USVString pathname; - readonly attribute USVString search; - readonly attribute USVString hash; -};
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces.worker.js deleted file mode 100644 index f07669b..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces.worker.js +++ /dev/null
@@ -1,20 +0,0 @@ -"use strict"; - -importScripts("/resources/testharness.js"); -importScripts("/resources/WebIDLParser.js", "/resources/idlharness.js"); - -var request = new XMLHttpRequest(); -request.onload = function() { - var idlArray = new IdlArray(); - var idls = request.responseText; - idlArray.add_idls(idls); - idlArray.add_objects({ - DedicatedWorkerGlobalScope: ['self'], - WorkerNavigator: ['self.navigator'], - WorkerLocation: ['self.location'], - }); - idlArray.test(); - done(); -}; -request.open("GET", "interfaces.idl"); -request.send();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/EventTarget.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/EventTarget.worker.js deleted file mode 100644 index 954c46c..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/EventTarget.worker.js +++ /dev/null
@@ -1,23 +0,0 @@ -importScripts("/resources/testharness.js"); - -test(function(t) { - var i = 0; - addEventListener("message", function listener(evt) { - t.step(function() { - ++i; - removeEventListener("message", listener, true); - }); - }, true); - self.dispatchEvent(new Event("message")); - self.dispatchEvent(new Event("message")); - assert_equals(i, 1); -}, "removeEventListener"); - -test(function() { - addEventListener("message", this.step_func(function(evt) { - assert_equals(evt.target, self); - }), true); - self.dispatchEvent(new Event("message")); -}, "target"); - -done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/onmessage.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/onmessage.worker.js deleted file mode 100644 index 6f285ca..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/onmessage.worker.js +++ /dev/null
@@ -1,40 +0,0 @@ -importScripts("/resources/testharness.js"); - -test(function() { - self.onmessage = 1; - assert_equals(self.onmessage, null, - "attribute should return null after being set to a primitive"); -}, "Setting onmessage to 1"); - -test(function() { - var object = { - handleEvent: this.unreached_func() - }; - self.onmessage = object; - assert_equals(self.onmessage, object, - "attribute should return the object it was set to."); - - self.dispatchEvent(new Event("message")); -}, "Setting onmessage to an object"); - -test(function() { - var triggered = false; - var f = function(e) { triggered = true; }; - self.onmessage = f; - assert_equals(self.onmessage, f, - "attribute should return the function it was set to."); - - self.dispatchEvent(new Event("message")); - assert_true(triggered, "event handler should have been triggered"); -}, "Setting onmessage to a function"); - - -test(function() { - assert_not_equals(self.onmessage, null, - "attribute should not return null after being set to a function"); - self.onmessage = 1; - assert_equals(self.onmessage, null, - "attribute should return null after being set to a primitive"); -}, "Setting onmessage to 1 (again)"); - -done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/event-ports-dedicated.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/event-ports-dedicated.html deleted file mode 100644 index 7ae4b07..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/event-ports-dedicated.html +++ /dev/null
@@ -1,25 +0,0 @@ -<!-- -onmessage = function(e) { - postMessage(e.ports instanceof Array && e.ports.length === 0); -} -/* ---> -<!doctype html> -<title>e.ports in dedicated worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -(async_test()).step(function() { - var worker = new Worker('#'); - worker.postMessage(1); - worker.onmessage = this.step_func(function(e) { - assert_true(e.data); - this.done(); - }); -}); -</script> -<!-- -*/ -//--> -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/imagedata-cloned-canvas-in-array.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/imagedata-cloned-canvas-in-array.html deleted file mode 100644 index 2041301..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/imagedata-cloned-canvas-in-array.html +++ /dev/null
@@ -1,39 +0,0 @@ -<!-- -onmessage = function(e) { - function processPixels(imagedata) { - var pixeldata = imagedata.data; - for (var i = 0; i < pixeldata.length; i = i+4) { - pixeldata[i] = 128; - } - postMessage(imagedata); - } - processPixels(e.data[0]); -} - -/* ---> -<!doctype html> -<title>posting an imagedata (from a cloned canvas) in an array</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -(async_test()).step(function() { - var worker = new Worker('#'); - var canvas = document.createElement('canvas'); - var clone = canvas.cloneNode(true); - var ctx = clone.getContext('2d'); - var imagedata = ctx.getImageData(0, 0, 300, 150); - worker.postMessage([imagedata]); - worker.onmessage = this.step_func(function(e) { - var pixeldata = e.data.data; - for (var i = 0; i < pixeldata.length; i++) { - assert_equals(pixeldata[i], (i % 4 == 0) ? 128 : 0); - } - this.done(); - }); -}); -</script> -<!-- -*/ -//--> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.html deleted file mode 100644 index 91ec632..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.html +++ /dev/null
@@ -1,23 +0,0 @@ -<!DOCTYPE html> -<meta charset=utf-8> -<title>'message' event properties</title> -<link rel=help href="http://www.whatwg.org/html/#dom-dedicatedworkerglobalscope-postmessage"> -<script src=/resources/testharness.js></script> -<script src=/resources/testharnessreport.js></script> -<div id=log></div> -<script> -async_test("Properties of the 'message' event").step(function() { - var worker = new Worker("message-event.js"); - worker.onmessage = this.step_func_done(function (evt) { - assert_class_string(evt, "MessageEvent"); - assert_equals(evt.type, "message"); - assert_false(evt.bubbles, "bubbles should be false"); - assert_false(evt.cancelable, "cancelable should be false"); - assert_equals(evt.data, "test"); - assert_equals(evt.origin, "", "origin"); - assert_equals(evt.lastEventId, "", "lastEventId"); - assert_equals(evt.source, null, "source"); - assert_array_equals(evt.ports, [], "ports"); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.js deleted file mode 100644 index 54a2500..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.js +++ /dev/null
@@ -1 +0,0 @@ -postMessage("test");
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/return-value.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/return-value.worker.js deleted file mode 100644 index 52125169..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/return-value.worker.js +++ /dev/null
@@ -1,8 +0,0 @@ -importScripts("/resources/testharness.js"); - -test(function() { - var rv = postMessage(1); - assert_equals(rv, undefined); -}, "return value of postMessage"); - -done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null-in-array.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null-in-array.html deleted file mode 100644 index df4c9f83..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null-in-array.html +++ /dev/null
@@ -1,26 +0,0 @@ -<!-- -try { - postMessage(false, [null]); -} catch(e) { - postMessage(e instanceof TypeError); -} -/* ---> -<!doctype html> -<title>Using [null] in postMessage's second argument</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -(async_test()).step(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_true(e.data); - this.done(); - }); -}); -</script> -<!-- -*/ -//--> -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null.html deleted file mode 100644 index e81a56ba..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null.html +++ /dev/null
@@ -1,25 +0,0 @@ -<!-- -try { - postMessage(1, null); -} catch(e) { - postMessage(e instanceof TypeError); -} -/* ---> -<!doctype html> -<title>Using null in postMessage's second argument</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -(async_test()).step(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_true(e.data); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-undefined.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-undefined.html deleted file mode 100644 index 7d01eba..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-undefined.html +++ /dev/null
@@ -1,25 +0,0 @@ -<!-- -try { - postMessage(1, undefined); -} catch(e) { - postMessage(''+e); -} -/* ---> -<!doctype html> -<title>Using undefined in postMessage's second argument</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -(async_test()).step(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data, 1); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/setting-postMessage.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/setting-postMessage.html deleted file mode 100644 index d1a3f0f..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/setting-postMessage.html +++ /dev/null
@@ -1,24 +0,0 @@ -<!-- -var x = postMessage; -postMessage = 1; -x(postMessage == 1); - -/* ---> -<!doctype html> -<title>setting postMessage</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -(async_test()).step(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_true(e.data); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-imagedata.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-imagedata.html deleted file mode 100644 index c0ded6a..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-imagedata.html +++ /dev/null
@@ -1,30 +0,0 @@ -<!-- -onmessage = function(e) { - var imagedata = e.data; - imagedata.data[0] = 128; - postMessage(imagedata); -} - -/* ---> -<!doctype html> -<title>structured clone of ImageData</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -(async_test()).step(function() { - var worker = new Worker('#'); - var ctx = document.createElement('canvas').getContext('2d'); - var imagedata = ctx.getImageData(0, 0, 300, 150); - worker.postMessage(imagedata); - worker.onmessage = this.step_func(function(e) { - assert_equals(''+e.data, '[object ImageData]'); - assert_equals(e.data.data[0], 128); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-message.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-message.html deleted file mode 100644 index ba357421f..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-message.html +++ /dev/null
@@ -1,58 +0,0 @@ -<!-- -var err = new Error('foo'); -var date = new Date(); -// commented out bits are either tested elsewhere or not supported yet. or uncloneable. -var tests = [undefined, null, false, true, 1, NaN, Infinity, 'foo', date, /foo/, /* ImageData, File, FileData, FileList,*/ null/*self*/, - [undefined, null, false, true, 1, NaN, Infinity, 'foo', /*date, /foo/,*/ null/*self*/, /*[], {},*/ null/*err*/], - {a:undefined, b:null, c:false, d:true, e:1, f:NaN, g:Infinity, h:'foo', /*i:date, j:/foo/,*/ k:null/*self*/, /*l:[], m:{},*/ n:null/*err*/}, - null/*err*/]; -for (var i = 0; i < tests.length; ++i) { - try { - postMessage(tests[i]); - } catch(e) { - postMessage(''+e); - } -} -/* ---> -<!doctype html> -<title>structured clone of message</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -var wrapper_test = async_test(); -var tests = [ - {test:async_test('undefined'), check:function(e) { assert_equals(e.data, undefined); }}, - {test:async_test('null'), check:function(e) { assert_equals(e.data, null); }}, - {test:async_test('false'), check:function(e) { assert_false(e.data); }}, - {test:async_test('true'), check:function(e) { assert_true(e.data); }}, - {test:async_test('1'), check:function(e) { assert_equals(e.data, 1); }}, - {test:async_test('NaN'), check:function(e) { assert_equals(e.data, NaN); }}, - {test:async_test('Infinity'), check:function(e) { assert_equals(e.data, Infinity); }}, - {test:async_test('string'), check:function(e) { assert_equals(e.data, 'foo'); }}, - {test:async_test('date'), check:function(e) { assert_equals(e.data instanceof Date, true); }}, - {test:async_test('regexp'), check:function(e) { assert_equals('' + e.data, '/foo/'); assert_equals(e.data instanceof RegExp, true, 'e.data instanceof RegExp'); }}, - {test:async_test('self'), check:function(e) { assert_equals(e.data, null); }}, - {test:async_test('array'), check:function(e) { assert_array_equals(e.data, [undefined, null, false, true, 1, NaN, Infinity, 'foo', null, null]); }}, - {test:async_test('object'), check:function(e) { assert_object_equals(e.data, {a:undefined, b:null, c:false, d:true, e:1, f:NaN, g:Infinity, h:'foo', k:null, n:null}); }}, - {test:async_test('error'), check:function(e) { assert_equals(e.data, null, 'new Error()'); }}, - {test:wrapper_test, check:function(e) { assert_unreached(); }} -]; -// make wrapper_test pass after 500ms -setTimeout(tests[tests.length-1].test.step_func(function() { - this.done(); -}), 500); - -wrapper_test.step(function() { - var worker = new Worker('#'); - var i = 0; - worker.onmessage = function(e) { - tests[i].test.step(function() { tests[i].check(e); this.done(); }); - i++; - }; -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/SharedWorkerGlobalScope/name/getting.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/SharedWorkerGlobalScope/name/getting.html deleted file mode 100644 index bfe81a8..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/SharedWorkerGlobalScope/name/getting.html +++ /dev/null
@@ -1,34 +0,0 @@ -<!-- -addEventListener('connect', function(e) { - var passed; - switch (location.hash) { - case '#1': passed = name == ''; break; - case '#2': passed = name == 'a'; break; - case '#3': passed = name == '0'; break; - } - e.ports[0].postMessage(passed); -}, false); -/* ---> -<!doctype html> -<title>getting name</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -var tests = [['#1', ''], ['#2', 'a'], ['#3', -0]]; -tests.forEach(function(t) { - async_test(function() { - var w = new SharedWorker(t[0], t[1]); - w.port.onmessage = this.step_func(function(e) { - assert_true(e.data); - this.done(); - }); - }); -}); -</script> -<!-- -*/ -//--> - -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/SharedWorkerGlobalScope/name/setting.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/SharedWorkerGlobalScope/name/setting.html deleted file mode 100644 index 39cdf7b6..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/SharedWorkerGlobalScope/name/setting.html +++ /dev/null
@@ -1,25 +0,0 @@ -<!-- -addEventListener('connect', function(e) { - name = 1; - e.ports[0].postMessage(name); -}, false); -/* ---> -<!doctype html> -<title>setting name</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var w1 = new SharedWorker('#1', 'x'); - w1.port.addEventListener('message', this.step_func(function(e) { - assert_equals(e.data, 'x'); - this.done(); - }), false); - w1.port.start(); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/SharedWorkerGlobalScope/onconnect.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/SharedWorkerGlobalScope/onconnect.html deleted file mode 100644 index 2ad155b..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/SharedWorkerGlobalScope/onconnect.html +++ /dev/null
@@ -1,39 +0,0 @@ -<!-- -var results = []; -try { - self.onconnect = 1; - results.push(String(onconnect)); -} catch(e) { - results.push(''+e); -} -try { - self.onconnect = {handleEvent:function(){}}; - results.push(String(onconnect)); -} catch(e) { - results.push(''+e); -} -var f = function(e) { - results.push(e.data); - e.ports[0].postMessage(results); -}; -onconnect = f; -results.push(typeof onconnect); -/* ---> -<!doctype html> -<title>onconnect</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var w1 = new SharedWorker('#', ''); - w1.port.addEventListener('message', this.step_func(function(e) { - assert_array_equals(e.data, ['null', 'null', 'function', '']); - }), false); - w1.port.start(); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/incoming-message.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/incoming-message.html deleted file mode 100644 index d656956..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/incoming-message.html +++ /dev/null
@@ -1,29 +0,0 @@ -<!-- -onmessage = function(e) { - postMessage(1); - throw new Error(); -} -close(); -/* ---> -<!doctype html> -<title>close() and incoming message</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -var worker = new Worker('#'); -worker.onmessage = function(e) { - assert_unreached("Got message"); -}; -worker.onerror = function(e) { - assert_unreached("Got error"); -}; -worker.postMessage(1); -setTimeout(done, 2000); -</script> -<!-- -*/ -//--> - -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/sending-messages.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/sending-messages.html deleted file mode 100644 index 983c422..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/sending-messages.html +++ /dev/null
@@ -1,27 +0,0 @@ -<!-- -postMessage(1); -close(); -postMessage(2); -/* ---> -<!doctype html> -<title>close() and sending messages</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var worker = new Worker('#'); - var i = 0; - worker.onmessage = this.step_func(function(e) { - i++; - assert_equals(e.data, i); - if (i == 2) { - this.done(); - } - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/setInterval.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/setInterval.html deleted file mode 100644 index 1d7d178d..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/setInterval.html +++ /dev/null
@@ -1,34 +0,0 @@ -<!-- -var interval1 = setInterval(function() { - clearInterval(interval1); - postMessage(1); - throw new Error(); -}, 10); -close(); -var interval2 = setInterval(function() { - clearInterval(interval2); - postMessage(1); - throw new Error(); -}, 10); -/* ---> -<!doctype html> -<title>close() and setInterval</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -var worker = new Worker('#'); -worker.onmessage = function(e) { - assert_unreached("Got message"); -}; -worker.onerror = function(e) { - assert_unreached("Got error"); -}; -setTimeout(done, 2000); -</script> -<!-- -*/ -//--> - -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/setTimeout.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/setTimeout.html deleted file mode 100644 index c2fa10df..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/setTimeout.html +++ /dev/null
@@ -1,28 +0,0 @@ -<!-- -function x() { - postMessage(1); - throw new Error(); -} -setTimeout(x, 0); -close(); -setTimeout(x, 0); -/* ---> -<!doctype html> -<title>close() and setTimeout</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -var worker = new Worker('#'); -worker.onmessage = function(e) { - assert_unreached("Got message"); -}; -worker.onerror = function(e) { - assert_unreached("Got error"); -}; -setTimeout(done, 2000); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/helper-redirect.py b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/helper-redirect.py deleted file mode 100644 index eb1599a5..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/helper-redirect.py +++ /dev/null
@@ -1,3 +0,0 @@ -def main(request, response): - response.status = 302 - response.headers.append("Location", "post-location-members.js?a")
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/members.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/members.html deleted file mode 100644 index 31ddf37..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/members.html +++ /dev/null
@@ -1,31 +0,0 @@ -<!-- -postMessage([null, location.href, location.protocol, location.host, - location.hostname, location.port, location.pathname, - location.search, location.hash]); -/* ---> -<!doctype html> -<title>members of WorkerLocation</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data[0], null); - assert_equals(e.data[1], location.href + '#', 'href'); - assert_equals(e.data[2], location.protocol, 'protocol'); - assert_equals(e.data[3], location.host, 'host'); - assert_equals(e.data[4], location.hostname, 'hostname'); - assert_equals(e.data[5], location.port, 'port'); - assert_equals(e.data[6], location.pathname, 'pathname'); - assert_equals(e.data[7], location.search, 'search'); - assert_equals(e.data[8], '', 'hash'); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/post-location-members.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/post-location-members.js deleted file mode 100644 index e850b76..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/post-location-members.js +++ /dev/null
@@ -1,8 +0,0 @@ -postMessage([location.href, - location.protocol, - location.host, - location.hostname, - location.port, - location.pathname, - location.search, - location.hash]); \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/redirect.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/redirect.html deleted file mode 100644 index 2fd16a4..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/redirect.html +++ /dev/null
@@ -1,28 +0,0 @@ -<!-- -/* ---> -<!doctype html> -<title>location with a worker in separate file that redirects</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var worker = new Worker('helper-redirect.py?fail'); - worker.onmessage = this.step_func_done(function(e) { - assert_equals(e.data[0], location.href.replace(/\/[^\/]+$/, '/post-location-members.js?a')); - assert_equals(e.data[1], location.protocol); - assert_equals(e.data[2], location.host); - assert_equals(e.data[3], location.hostname); - assert_equals(e.data[4], location.port); - assert_equals(e.data[5], location.pathname.replace(/\/[^\/]+$/, '/post-location-members.js')); - assert_equals(e.data[6], '?a'); - assert_equals(e.data[7], ''); - }); -}); -</script> -<!-- -*/ -//--> - -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/returns-same-object.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/returns-same-object.html deleted file mode 100644 index 40559c16..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/returns-same-object.html +++ /dev/null
@@ -1,21 +0,0 @@ -<!-- -postMessage(location === location); -/* ---> -<!doctype html> -<title>location === location</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_true(e.data); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/setting-members.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/setting-members.html deleted file mode 100644 index d2f470f..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/setting-members.html +++ /dev/null
@@ -1,43 +0,0 @@ -<!-- -var exceptions = []; -try { location.href = 1; } catch(e) { exceptions.push('href'); } -try { location.protocol = 1; } catch(e) { exceptions.push('protocol'); } -try { location.host = 1; } catch(e) { exceptions.push('host'); } -try { location.hostname = 1; } catch(e) { exceptions.push('hostname');} -try { location.port = 1; } catch(e) { exceptions.push('port'); } -try { location.pathname = 1; } catch(e) { exceptions.push('pathname'); } -try { location.search = 1; } catch(e) { exceptions.push('search'); } -try { location.hash = 1; } catch(e) { exceptions.push('hash'); } - -postMessage([null, location.href, location.protocol, location.host, - location.hostname, location.port, location.pathname, - location.search, location.hash, exceptions]); -/* ---> -<!doctype html> -<title>setting members of WorkerLocation</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data[0], null); - assert_equals(e.data[1], location.href + '#', 'href'); - assert_equals(e.data[2], location.protocol, 'protocol'); - assert_equals(e.data[3], location.host, 'host'); - assert_equals(e.data[4], location.hostname, 'hostname'); - assert_equals(e.data[5], location.port, 'port'); - assert_equals(e.data[6], location.pathname, 'pathname'); - assert_equals(e.data[7], location.search, 'search'); - assert_equals(e.data[8], '', 'hash'); - assert_array_equals(e.data[9], [], 'number of exceptions'); - this.done(); - }); -}); -</script> -<!-- -*/ -//--> -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/worker-separate-file.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/worker-separate-file.html deleted file mode 100644 index ac8e64d..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/worker-separate-file.html +++ /dev/null
@@ -1,28 +0,0 @@ -<!-- -/* ---> -<!doctype html> -<title>location with a worker in separate file</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var worker = new Worker('post-location-members.js?a#b?c'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data[0], location.href.replace(/\/[^\/]+$/, '/post-location-members.js?a#b?c')); - assert_equals(e.data[1], location.protocol); - assert_equals(e.data[2], location.host); - assert_equals(e.data[3], location.hostname); - assert_equals(e.data[4], location.port); - assert_equals(e.data[5], location.pathname.replace(/\/[^\/]+$/, '/post-location-members.js')); - assert_equals(e.data[6], '?a'); - assert_equals(e.data[7], '#b?c'); - this.done(); - }); -}); -</script> -<!-- -*/ -//--> -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/exception-in-onerror.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/exception-in-onerror.html deleted file mode 100644 index 4b5af71..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/exception-in-onerror.html +++ /dev/null
@@ -1,32 +0,0 @@ -<!-- -onerror = function(a, b, c, d) { - y(); // the error is "not handled" -} -function x() { - y(); -} -x(); -/* ---> -<!doctype html> -<title>onerror, "not handled" with an error in the onerror function</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onerror = this.step_func(function(e) { - assert_true(e instanceof ErrorEvent, 'e instanceof ErrorEvent'); - assert_equals(typeof e.message, 'string', 'typeof e.message'); - assert_equals(e.filename, document.URL+'#', 'e.filename'); - assert_equals(typeof e.lineno, 'number', 'typeof e.lineno'); - assert_equals(typeof e.colno, 'number', 'typeof e.column'); - e.preventDefault(); // "handled" - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/handled.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/handled.html deleted file mode 100644 index 56fee8e..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/handled.html +++ /dev/null
@@ -1,36 +0,0 @@ -<!-- -onerror = function(a, b, c, d) { - postMessage([a, b, c, d]); - return true; // the error is "handled" -} -function x() { - y(); -} -x(); -/* ---> -<!doctype html> -<title>onerror, "handled"</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(typeof e.data[0], 'string', 'first argument'); - assert_equals(e.data[1], document.URL+'#', 'second argument'); - assert_equals(typeof e.data[2], 'number', 'third argument'); - assert_equals(typeof e.data[3], 'number', 'fourth argument'); - setTimeout(this.step_func(function() { - this.done(); - }), 100); - }); - worker.onerror = this.step_func(function(e) { - assert_unreached(); - }); -}); -</script> -<!-- -*/ -//--> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/not-handled.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/not-handled.html deleted file mode 100644 index f6107ad..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/not-handled.html +++ /dev/null
@@ -1,32 +0,0 @@ -<!-- -onerror = function(a, b, c, d) { - return false; // the error is "not handled" -} -function x() { - y(); -} -x(); -/* ---> -<!doctype html> -<title>onerror, "not handled"</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onerror = this.step_func(function(e) { - assert_true(e instanceof ErrorEvent, 'e instanceof ErrorEvent'); - assert_equals(typeof e.message, 'string', 'typeof e.message'); - assert_equals(e.filename, document.URL+'#', 'e.filename'); - assert_equals(typeof e.lineno, 'number', 'typeof e.lineno'); - assert_equals(typeof e.colno, 'number', 'typeof e.column'); - e.preventDefault(); // "handled" - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html deleted file mode 100644 index b6a61e2..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html +++ /dev/null
@@ -1,31 +0,0 @@ -<!-- -function x() { - y(); -} -x(); -/* ---> -<!doctype html> -<title>onerror, "not handled" with only window.onerror defined</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -setup({ - allow_uncaught_exception: true, -}); -async_test(function() { - var worker = new Worker('#'); - window.onerror = this.step_func(function(a, b, c, d) { - assert_equals(typeof a, 'string', 'first argument'); - assert_equals(b, document.URL+'#', 'second argument'); - assert_equals(typeof c, 'number', 'third argument'); - assert_equals(typeof d, 'number', 'fourth argument'); - this.done(); - return true; // "handled" - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/self.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/self.html deleted file mode 100644 index 39c2c36..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/self.html +++ /dev/null
@@ -1,39 +0,0 @@ -<!-- -var results = []; -function check(func, msg) { - try { - results.push([func(), msg]); - } catch(ex) { - results.push([String(ex), msg]); - } -} -check(function() { return self === self; }, 'self === self'); -check(function() { return self instanceof WorkerGlobalScope; }, 'self instanceof WorkerGlobalScope'); -check(function() { return 'self' in self; }, '\'self\' in self'); -check(function() { - var x = self; - self = 1; - return x === self; -}, 'self = 1'); -postMessage(results); -/* ---> -<!doctype html> -<title>self</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - for (var i = 0; i < e.data.length; ++i) { - assert_true(e.data[i][0], e.data[i][1]); - } - this.done(); - }); -}); -</script> -<!-- -*/ -//--> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/001.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/001.html deleted file mode 100644 index a808975..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/001.html +++ /dev/null
@@ -1,23 +0,0 @@ -<!-- -setTimeout(function() { postMessage(1) }, 10); -/* ---> -<!doctype html> -<title>setTimeout</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data, 1); - this.done(); - }); -}); -</script> -<!-- -*/ -//--> - -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/002.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/002.html deleted file mode 100644 index 06685a9..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/002.html +++ /dev/null
@@ -1,21 +0,0 @@ -<!-- -var t = setTimeout(function() { postMessage(1); }, 10); -clearTimeout(t); -/* ---> -<!doctype html> -<title>clearTimeout</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var worker = new Worker('#'); - var gotMessage = false; - worker.onmessage = function() { gotMessage = true; }; - setTimeout(this.step_func(function() { assert_false(gotMessage); this.done(); }), 100); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/003.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/003.html deleted file mode 100644 index 942f139..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/003.html +++ /dev/null
@@ -1,22 +0,0 @@ -<!-- -setInterval(function() { postMessage(1); }, 10); -/* ---> -<!doctype html> -<title>setInterval</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data, 1); - this.done(); - }); -}); -</script> -<!-- -*/ -//--> -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/004.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/004.html deleted file mode 100644 index 5548eec..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/004.html +++ /dev/null
@@ -1,23 +0,0 @@ -<!-- -var t = setInterval(function() { - postMessage(1); -}, 10); -clearInterval(t); -/* ---> -<!doctype html> -<title>clearInterval</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var worker = new Worker('#'); - var i = 0; - worker.onmessage = function() { i++; } - setTimeout(this.step_func(function() { assert_equals(i, 0); this.done(); }), 100); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/001.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/001.worker.js deleted file mode 100644 index aa86c8ef..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/001.worker.js +++ /dev/null
@@ -1,7 +0,0 @@ -importScripts("/resources/testharness.js"); - -test(function() { - importScripts(); -}); - -done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/002.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/002.worker.js deleted file mode 100644 index 2cecbcb..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/002.worker.js +++ /dev/null
@@ -1,11 +0,0 @@ -importScripts("/resources/testharness.js"); - -test(function() { - var ran = false; - assert_throws("SyntaxError", function() { - importScripts('data:text/javascript,ran=true','http://foo bar'); - }); - assert_false(ran, 'first argument to importScripts ran'); -}); - -done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/003.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/003.html deleted file mode 100644 index 7ff30ae..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/003.html +++ /dev/null
@@ -1,28 +0,0 @@ -<!-- -var x = 'a'; -try { - importScripts('data:text/javascript,x+="b"', - 'data:text/javascript,x+="c"'); -} catch(e) { - x += "d" -} -postMessage(x); -/* ---> -<!doctype html> -<title>importScripts running scripts</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data, "abc"); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/004.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/004.html deleted file mode 100644 index 2d39d3ce..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/004.html +++ /dev/null
@@ -1,34 +0,0 @@ -<!-- -var x = ''; -var exception; -try { - importScripts('data:text/javascript,x+="first script successful. "', - 'data:text/javascript,x+="FAIL (second script). "; for(;) break;', // doesn't compile - 'data:text/javascript,x+="FAIL (third script)"'); -} catch(ex) { - if (ex instanceof SyntaxError) - exception = true; - else - exception = String(ex); -} -postMessage([x, exception]); -/* ---> -<!doctype html> -<title>importScripts broken script</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data[0], "first script successful. "); - assert_true(e.data[1], 'expected SyntaxError'); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/005.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/005.html deleted file mode 100644 index f8abe14..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/005.html +++ /dev/null
@@ -1,30 +0,0 @@ -<!-- -var x; -var y; -try { - importScripts('data:text/javascript,x={', - 'data:text/javascript,}'); -} catch(e) { - y = true; -} -postMessage([x, y]); -/* ---> -<!doctype html> -<title>importScripts separate scripts</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data[0], undefined); - assert_true(e.data[1]); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/006.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/006.html deleted file mode 100644 index 06aea96..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/006.html +++ /dev/null
@@ -1,33 +0,0 @@ -<!-- -var x; -var y; -var z; -try { - importScripts('data:text/javascript,x=1', - 'data:text/javascript,throw 2', - 'data:text/javascript,z=3'); -} catch(e) { - y = e; -} -postMessage([x, y, z]); -/* ---> -<!doctype html> -<title>importScripts uncaught exception</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data[0], 1); - assert_equals(e.data[1], 2); - assert_equals(e.data[2], undefined); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/007.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/007.html deleted file mode 100644 index 128fb1b..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/007.html +++ /dev/null
@@ -1,25 +0,0 @@ -<!-- -importScripts('data:text/javascript,postMessage(1)'); -postMessage(2); -/* ---> -<!doctype html> -<title>postMessage in importScripts</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var worker = new Worker('#'); - var i = 0; - worker.onmessage = this.step_func(function(e) { - i++; - assert_equals(e.data, i); - if (i == 2) - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/008.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/008.html deleted file mode 100644 index 07b800eb..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/008.html +++ /dev/null
@@ -1,23 +0,0 @@ -<!-- -var log = postMessage; -importScripts('data:text/javascript,function run() { log(true) }'); -run(); -/* ---> -<!doctype html> -<title>variables and functions crossing importScripts boundary</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_true(e.data); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/009.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/009.html deleted file mode 100644 index 95d3839d..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/009.html +++ /dev/null
@@ -1,29 +0,0 @@ -<!-- -var log = postMessage; -importScripts('data:text/javascript,function run() { for(var i = 0; i < 1000; ++i) { if (i == 500) log(true); } return 1; }'); -postMessage(run()); -/* ---> -<!doctype html> -<title>variables and functions crossing importScripts boundary, take 2</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var worker = new Worker('#'); - var i = 0; - worker.onmessage = this.step_func(function(e) { - i++; - if (i == 1) { - assert_true(e.data); - } else { - assert_equals(e.data, 1); - this.done(); - } - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/010.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/010.html deleted file mode 100644 index 9c76e7d..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/010.html +++ /dev/null
@@ -1,34 +0,0 @@ -<!-- -// prevent recursion -if ('beenThere' in self) { - throw 'undefined stringified to the empty string'; -} -beenThere = true; -try { - importScripts(undefined); - postMessage(got); -} catch(ex) { - postMessage(String(ex)); -} -/* ---> -<!doctype html> -<title>importScripts(undefined)</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data, 'undefined'); - this.done(); - }) - worker.onerror = this.step_func(function(e) { - assert_unreached(e.message); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/011.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/011.html deleted file mode 100644 index 46499318..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/011.html +++ /dev/null
@@ -1,34 +0,0 @@ -<!-- -// prevent recursion -if ('beenThere' in self) { - throw 'null stringified to the empty string'; -} -beenThere = true; -try { - importScripts(null); - postMessage(got); -} catch(ex) { - postMessage(String(ex)); -} -/* ---> -<!doctype html> -<title>importScripts(null)</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data, 'null'); - this.done(); - }); - worker.onerror = this.step_func(function(e) { - assert_unreached(e.message); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/012.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/012.html deleted file mode 100644 index f7622bd..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/012.html +++ /dev/null
@@ -1,34 +0,0 @@ -<!-- -// prevent recursion -if ('beenThere' in self) { - throw '1 stringified to the empty string'; -} -beenThere = true; -try { - importScripts(1); - postMessage(got); -} catch(ex) { - postMessage(String(ex)); -} -/* ---> -<!doctype html> -<title>importScripts(1)</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id="log"></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data, '1'); - this.done(); - }); - worker.onerror = this.step_func(function(e) { - assert_unreached(e.message); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/1 b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/1 deleted file mode 100644 index 18cea4f..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/1 +++ /dev/null
@@ -1 +0,0 @@ -var got = '1'; \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/null b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/null deleted file mode 100644 index 8e54b66c..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/null +++ /dev/null
@@ -1 +0,0 @@ -var got = 'null'; \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/undefined b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/undefined deleted file mode 100644 index f99ba4b..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/undefined +++ /dev/null
@@ -1 +0,0 @@ -var got = 'undefined'; \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/002.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/002.html deleted file mode 100644 index d3aa2ec..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/002.html +++ /dev/null
@@ -1,21 +0,0 @@ -<!-- -postMessage(navigator.appName); -/* ---> -<!doctype html> -<title>navigator.appName</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data, navigator.appName); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/003.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/003.html deleted file mode 100644 index a2e5c948..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/003.html +++ /dev/null
@@ -1,21 +0,0 @@ -<!-- -postMessage(navigator.appVersion); -/* ---> -<!doctype html> -<title>navigator.appVersion</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data, navigator.appVersion); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/004.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/004.html deleted file mode 100644 index 2231c4ab..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/004.html +++ /dev/null
@@ -1,21 +0,0 @@ -<!-- -postMessage(navigator.platform); -/* ---> -<!doctype html> -<title>navigator.platform</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data, navigator.platform); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/005.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/005.html deleted file mode 100644 index b3d99588..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/005.html +++ /dev/null
@@ -1,21 +0,0 @@ -<!-- -postMessage(navigator.userAgent); -/* ---> -<!doctype html> -<title>navigator.userAgent</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data, navigator.userAgent); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/006.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/006.html deleted file mode 100644 index c027d63..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/006.html +++ /dev/null
@@ -1,21 +0,0 @@ -<!-- -postMessage(navigator.onLine); -/* ---> -<!doctype html> -<title>navigator.onLine</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data, navigator.onLine); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/007.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/007.html deleted file mode 100644 index a6afc56..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/007.html +++ /dev/null
@@ -1,30 +0,0 @@ -<!-- -var log = []; -var neverEncounteredValue = "This is not the value you are looking for."; -for (x in navigator) { - // this should silently fail and not throw per webidl - navigator[x] = neverEncounteredValue; - if (navigator[x] === neverEncounteredValue) - log.push(x); -} -postMessage(log.join(', ')); -/* ---> -<!doctype html> -<title>readonlyness of members of Navigator</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data, ''); - this.done(); - }); -}); -</script> -<!-- -*/ -//--> -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/language.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/language.html deleted file mode 100644 index f1aa446c..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/language.html +++ /dev/null
@@ -1,21 +0,0 @@ -<!-- -postMessage(navigator.language); -/* ---> -<!doctype html> -<title>navigator.language</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data, navigator.language); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/nested_worker.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/nested_worker.worker.js deleted file mode 100644 index 8848fa2..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/nested_worker.worker.js +++ /dev/null
@@ -1,11 +0,0 @@ -importScripts("/resources/testharness.js"); - -async_test(function() { - var worker1 = new Worker("support/WorkerBasic.js"); - worker1.postMessage("ping"); - worker1.onmessage = this.step_func_done(function(evt) { - assert_equals(evt.data, "Pass"); - worker1.terminate(); - done(); - }); -}, "Nested worker");
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/application-cache-dedicated.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/application-cache-dedicated.js deleted file mode 100644 index 2318c2e..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/application-cache-dedicated.js +++ /dev/null
@@ -1 +0,0 @@ -postMessage(1); \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/cache.manifest b/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/cache.manifest deleted file mode 100644 index 8d80e03..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/cache.manifest +++ /dev/null
@@ -1,3 +0,0 @@ -CACHE MANIFEST -application-cache-dedicated.html -application-cache-dedicated.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/infinite-nested.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/infinite-nested.js deleted file mode 100644 index 137dd0a..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/infinite-nested.js +++ /dev/null
@@ -1,5 +0,0 @@ -postMessage(1); -var w = new Worker('infinite-nested.js'); -w.onmessage = function(e) { - postMessage(e.data); -} \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/infinite-sibling-and-nested.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/infinite-sibling-and-nested.js deleted file mode 100644 index cf7b794..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/infinite-sibling-and-nested.js +++ /dev/null
@@ -1,8 +0,0 @@ -function createWorker() { - var worker = new Worker('infinite-nested.js?' + Math.random()); - worker.onmessage = function(e) { - postMessage(e.data); - createWorker(); - } -} -createWorker(); \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/infinite-sibling.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/infinite-sibling.js deleted file mode 100644 index 6424f70..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/infinite-sibling.js +++ /dev/null
@@ -1,8 +0,0 @@ -function createWorker() { - var worker = new Worker('post-a-1.js?' + Math.random()); - worker.onmessage = function(e) { - postMessage(e.data); - createWorker(); - } -} -createWorker(); \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/post-a-1.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/post-a-1.js deleted file mode 100644 index 2318c2e..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/post-a-1.js +++ /dev/null
@@ -1 +0,0 @@ -postMessage(1); \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_DataCloneErr.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_DataCloneErr.htm deleted file mode 100644 index 24093ce4..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_DataCloneErr.htm +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title> postMessage() with WorkerNavigator </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var worker = new Worker("./support/WorkerDataCloneErr.js"); - worker.onmessage = t.step_func_done(function(e) { - assert_equals(e.data, "Pass"); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_clone_port.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_clone_port.htm deleted file mode 100644 index b1d7b84e..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_clone_port.htm +++ /dev/null
@@ -1,22 +0,0 @@ -<!DOCTYPE html> -<title> postMessage(): clone a port </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var channelA = new MessageChannel(); - var channelB = new MessageChannel(); - var originalPort = channelB.port2; - channelA.port2.onmessage = t.step_func(function(e) { - assert_equals(e.data, "ports"); - var clonedPort = e.ports[0]; - assert_not_equals(clonedPort, originalPort, "new cloned port object should not equal to the original port!"); - clonedPort.onmessage = t.step_func_done(function(e) { - assert_equals(e.data, "ping", "Data sent through remote port is received by the new cloned port"); - }); - }); - channelA.port1.postMessage("ports", [channelB.port2]); - channelB.port1.postMessage("ping"); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_clone_port_error.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_clone_port_error.htm deleted file mode 100644 index 3001296..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_clone_port_error.htm +++ /dev/null
@@ -1,14 +0,0 @@ -<!DOCTYPE html> -<title> postMessage(): cloning source port </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -test(function() { - var channel = new MessageChannel(); - channel.port1.start(); - assert_throws("DataCloneError", function() { - channel.port1.postMessage("ports", [channel.port1]); - }); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_event_properties.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_event_properties.htm deleted file mode 100644 index 8122413..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_event_properties.htm +++ /dev/null
@@ -1,24 +0,0 @@ -<!DOCTYPE html> -<title> postMessage(): MessageEvent properties </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var channel = new MessageChannel(); - var targetPort = channel.port2; - targetPort.start(); - targetPort.addEventListener("message", t.step_func_done(function (evt) { - assert_class_string(evt, "MessageEvent"); - assert_equals(evt.type, "message"); - assert_false(evt.bubbles, "bubbles should be false"); - assert_false(evt.cancelable, "cancelable should be false"); - assert_equals(evt.data, "ping", "data"); - assert_equals(evt.origin, "", "origin"); - assert_equals(evt.lastEventId, "", "lastEventId"); - assert_equals(evt.source, null, "source"); - assert_array_equals(evt.ports, [], "ports"); - }), true); - channel.port1.postMessage("ping"); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_ports_readonly_array.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_ports_readonly_array.htm deleted file mode 100644 index 5e2b905..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_ports_readonly_array.htm +++ /dev/null
@@ -1,20 +0,0 @@ -<!DOCTYPE html> -<title> postMessage(): read-only ports array </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var channel = new MessageChannel(); - var targetPort = channel.port2; - targetPort.start(); - targetPort.addEventListener("message", t.step_func_done(function(e) { - var channel3 = new MessageChannel(); - e.ports.push(channel3.port1); - e.ports.push(channel3.port1); - assert_equals(e.ports.length, 1, "ports is a read only array with length == 1."); - }), true); - var channel2 = new MessageChannel(); - channel.port1.postMessage("ports", [channel2.port1]); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_target_source.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_target_source.htm deleted file mode 100644 index 7d684916..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_target_source.htm +++ /dev/null
@@ -1,18 +0,0 @@ -<!DOCTYPE html> -<title> postMessage(): target port and source port </title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var channel = new MessageChannel(); - var source = channel.port1; - var target = channel.port2; - target.start(); - target.addEventListener("message", t.step_func_done(function(e) { - assert_equals(e.target, target); - assert_not_equals(e.target, source); - }), true); - source.postMessage("ping"); -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/001.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/001.html deleted file mode 100644 index 0ebec0b..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/001.html +++ /dev/null
@@ -1,21 +0,0 @@ -<!-- -postMessage('å'); -/* ---> -<!doctype html> -<title>encoding, dedicated worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data, '\u00e5'); - this.done(); - }); -}); -</script> -<!-- -*/ -//--> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/001.html.headers b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/001.html.headers deleted file mode 100644 index 2340a89c..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/001.html.headers +++ /dev/null
@@ -1 +0,0 @@ -Content-Type: text/html; charset=windows-1252
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/002.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/002.html deleted file mode 100644 index fdcc4f0..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/002.html +++ /dev/null
@@ -1,23 +0,0 @@ -<!-- -onconnect = function(e) { - e.ports[0].postMessage('å'); -} -/* ---> -<!doctype html> -<title>encoding, shared worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var worker = new SharedWorker('#', ''); - worker.port.onmessage = this.step_func(function(e) { - assert_equals(e.data, '\u00e5'); - this.done(); - }); -}); -</script> -<!-- -*/ -//--> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/002.html.headers b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/002.html.headers deleted file mode 100644 index 2340a89c..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/002.html.headers +++ /dev/null
@@ -1 +0,0 @@ -Content-Type: text/html; charset=windows-1252
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/003-1.py b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/003-1.py deleted file mode 100644 index 1e899aa..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/003-1.py +++ /dev/null
@@ -1,4 +0,0 @@ - # -*- coding: utf-8 -*- - -def main(request, response): - return "PASS" if request.GET.first('x') == 'å' else "FAIL"
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/003.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/003.html deleted file mode 100644 index a0f964c..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/003.html +++ /dev/null
@@ -1,26 +0,0 @@ -<!-- -var xhr = new XMLHttpRequest(); -xhr.open('GET', '003-1.py?x=å', false); -xhr.send(); -var passed = xhr.responseText == 'PASS'; -postMessage(passed); - -/* ---> -<!doctype html> -<title>URL encoding, dedicated worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_true(e.data); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/004.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/004.html deleted file mode 100644 index bb144263..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/004.html +++ /dev/null
@@ -1,27 +0,0 @@ -<!-- -onconnect = function(e) { - var xhr = new XMLHttpRequest(); - xhr.open('GET', '003-1.py?x=å', false); - xhr.send(); - var passed = xhr.responseText == 'PASS'; - e.ports[0].postMessage(passed); -} -/* ---> -<!doctype html> -<title>URL encoding, shared worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var worker = new SharedWorker('#'); - worker.port.onmessage = this.step_func(function(e) { - assert_true(e.data); - this.done(); - }); -}); -</script> -<!-- -*/ -//--> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/004.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/004.worker.js deleted file mode 100644 index 323d1c93..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/004.worker.js +++ /dev/null
@@ -1,5 +0,0 @@ -importScripts("/resources/testharness.js"); -test(function() { - assert_equals("ÿ", "\ufffd"); -}, "Decoding invalid utf-8"); -done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/001.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/001.worker.js deleted file mode 100644 index 23df42036..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/001.worker.js +++ /dev/null
@@ -1,79 +0,0 @@ -importScripts("/resources/testharness.js"); -var expected = [ - // https://html.spec.whatwg.org/ - "WorkerGlobalScope", - "DedicatedWorkerGlobalScope", - "Worker", - "SharedWorker", - "MessagePort", - "MessageEvent", - "WorkerNavigator", - "MessageChannel", - "WorkerLocation", - "ImageData", - "ImageBitmap", - "CanvasPath", - "Path2D", - "PromiseRejectionEvent", - "EventSource", - "WebSocket", - "CloseEvent", - "BroadcastChannel", - // https://tc39.github.io/ecma262/ - "ArrayBuffer", - "Int8Array", - "Uint8Array", - "Uint8ClampedArray", - "Int16Array", - "Uint16Array", - "Int32Array", - "Uint32Array", - "Float32Array", - "Float64Array", - "DataView", - // https://xhr.spec.whatwg.org/ - "XMLHttpRequestEventTarget", - "XMLHttpRequestUpload", - "XMLHttpRequest", - "ProgressEvent", - "FormData", - // https://url.spec.whatwg.org/ - "URL", - "URLSearchParams", - // https://w3c.github.io/FileAPI/ - "File", - "Blob", - "FileList", - "FileReader", - "FileReaderSync", - // https://dom.spec.whatwg.org/ - "EventTarget", - "ErrorEvent", - "Event", - "CustomEvent", - // http://heycam.github.io/webidl/ - "DOMException", - // https://streams.spec.whatwg.org/ - "ReadableStream", - "WritableStream", - "ByteLengthQueuingStrategy", - "CountQueuingStrategy", - // http://w3c.github.io/IndexedDB/ - "IDBRequest", - "IDBOpenDBRequest", - "IDBVersionChangeEvent", - "IDBFactory", - "IDBDatabase", - "IDBObjectStore", - "IDBIndex", - "IDBKeyRange", - "IDBCursor", - "IDBCursorWithValue", - "IDBTransaction", -]; -for (var i = 0; i < expected.length; ++i) { - test(function () { - assert_own_property(self, expected[i]); - }, "The " + expected[i] + " interface object should be exposed."); -} -done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/002.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/002.worker.js deleted file mode 100644 index 0f51498..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/002.worker.js +++ /dev/null
@@ -1,49 +0,0 @@ -importScripts("/resources/testharness.js"); -var unexpected = [ - // https://html.spec.whatwg.org/ - "SharedWorkerGlobalScope", - "AbstractView", - "AbstractWorker", - "ApplicationCache", - "Location", - "Navigator", - "Audio", - "HTMLCanvasElement", - "Path", - "TextMetrics", - "CanvasProxy", - "CanvasRenderingContext2D", - "DrawingStyle", - "CanvasGradient", - "CanvasPattern", - "PopStateEvent", - "HashChangeEvent", - "PageTransitionEvent", - // https://dom.spec.whatwg.org/ - "DOMImplementation", - // https://streams.spec.whatwg.org/ - "ReadableStreamDefaultReader", - "ReadableStreamBYOBReader", - "ReadableStreamDefaultController", - "ReadableByteStreamController", - "WritableStreamDefaultWriter", - "WritableStreamDefaultController", - // http://w3c.github.io/IndexedDB/ - "IDBEnvironment", - // https://www.w3.org/TR/2010/NOTE-webdatabase-20101118/ - "Database", - // https://w3c.github.io/uievents/ - "UIEvent", - "FocusEvent", - "MouseEvent", - "WheelEvent", - "InputEvent", - "KeyboardEvent", - "CompositionEvent", -]; -for (var i = 0; i < unexpected.length; ++i) { - test(function () { - assert_false(unexpected[i] in self); - }, "The " + unexpected[i] + " interface object should not be exposed."); -} -done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/003.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/003.html deleted file mode 100644 index 5277825d..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/003.html +++ /dev/null
@@ -1,106 +0,0 @@ -<!-- -onconnect = function(e) { - var expected = [ - // https://html.spec.whatwg.org/ - "ApplicationCache", - "WorkerGlobalScope", - "SharedWorkerGlobalScope", - "Worker", - "SharedWorker", - "MessagePort", - "MessageEvent", - "WorkerNavigator", - "MessageChannel", - "WorkerLocation", - "ImageData", - "ImageBitmap", - "CanvasPath", - "Path2D", - "PromiseRejectionEvent", - "EventSource", - "WebSocket", - "CloseEvent", - "BroadcastChannel", - // https://tc39.github.io/ecma262/ - "ArrayBuffer", - "Int8Array", - "Uint8Array", - "Uint8ClampedArray", - "Int16Array", - "Uint16Array", - "Int32Array", - "Uint32Array", - "Float32Array", - "Float64Array", - "DataView", - // https://xhr.spec.whatwg.org/ - "XMLHttpRequestEventTarget", - "XMLHttpRequestUpload", - "XMLHttpRequest", - "ProgressEvent", - "FormData", - // https://url.spec.whatwg.org/ - "URL", - "URLSearchParams", - // https://w3c.github.io/FileAPI/ - "File", - "Blob", - "FileList", - "FileReader", - "FileReaderSync", - // https://dom.spec.whatwg.org/ - "EventTarget", - "ErrorEvent", - "Event", - "CustomEvent", - // http://heycam.github.io/webidl/ - "DOMException", - // https://streams.spec.whatwg.org/ - "ReadableStream", - "WritableStream", - "ByteLengthQueuingStrategy", - "CountQueuingStrategy", - // http://w3c.github.io/IndexedDB/ - "IDBRequest", - "IDBOpenDBRequest", - "IDBVersionChangeEvent", - "IDBFactory", - "IDBDatabase", - "IDBObjectStore", - "IDBIndex", - "IDBKeyRange", - "IDBCursor", - "IDBCursorWithValue", - "IDBTransaction", - ]; - var result = []; - for (var i = 0; i < expected.length; ++i) { - result.push([expected[i], expected[i] in self]); - } - e.ports[0].postMessage(result); -} -/* ---> -<!doctype html> -<title>available interface objects in shared worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -setup(function() { - window.worker = new SharedWorker('#'); - worker.port.onmessage = function(e) { - var result = e.data; - for (var i = 0; i < result.length; ++i) { - test(function() { - assert_true(result[i][1]); - }, "The " + result[i][0] + " interface object should be exposed"); - } - done(); - } -}, {explicit_done: true}); -</script> -<!-- -*/ -//--> -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/004.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/004.html deleted file mode 100644 index 2e4387e..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/004.html +++ /dev/null
@@ -1,73 +0,0 @@ -<!-- -onconnect = function(e) { - var unexpected = [ - // https://html.spec.whatwg.org/ - "DedicatedWorkerGlobalScope", - "AbstractView", - "AbstractWorker", - "Location", - "Navigator", - "DOMImplementation", - "Audio", - "HTMLCanvasElement", - "Path", - "TextMetrics", - "CanvasProxy", - "CanvasRenderingContext2D", - "DrawingStyle", - "CanvasGradient", - "CanvasPattern", - "PopStateEvent", - "HashChangeEvent", - "PageTransitionEvent", - // https://streams.spec.whatwg.org/ - "ReadableStreamDefaultReader", - "ReadableStreamBYOBReader", - "ReadableStreamDefaultController", - "ReadableByteStreamController", - "WritableStreamDefaultWriter", - "WritableStreamDefaultController", - // http://w3c.github.io/IndexedDB/ - "IDBEnvironment", - // https://www.w3.org/TR/2010/NOTE-webdatabase-20101118/ - "Database", - // https://w3c.github.io/uievents/ - "UIEvent", - "FocusEvent", - "MouseEvent", - "WheelEvent", - "InputEvent", - "KeyboardEvent", - "CompositionEvent", - ]; - var result = []; - for (var i = 0; i < unexpected.length; ++i) { - result.push([unexpected[i], unexpected[i] in self]); - } - e.ports[0].postMessage(result); -} -/* ---> -<!doctype html> -<title>unavailable interface objects in shared worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -setup(function() { - window.worker = new SharedWorker('#'); - worker.port.onmessage = function(e) { - var result = e.data; - for (var i = 0; i < result.length; ++i) { - test(function() { - assert_false(result[i][1]); - }, "The " + result[i][0] + " interface object should not be exposed"); - } - done(); - } -}, {explicit_done: true}); -</script> -<!-- -*/ -//--> -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/001.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/001.html deleted file mode 100644 index 82ddcc3..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/001.html +++ /dev/null
@@ -1,41 +0,0 @@ -<!-- -if ('onmessage' in self) { // dedicated worker - onmessage = function(e) { - postMessage(e.data); - } -} else { // shared worker - onconnect = function(e) { - e.ports[0].onmessage = function(e) { - this.postMessage(e.data); - } - } -} -/* ---> -<!doctype html> -<title>dedicated and shared worker in same page</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data, 'dedicated'); - this.done(); - }); - worker.postMessage('dedicated'); -}, 'dedicated'); -async_test(function() { - var shared = new SharedWorker('#', ''); - shared.port.onmessage = this.step_func(function(e) { - assert_equals(e.data, 'shared'); - this.done(); - }); - shared.port.postMessage('shared'); -}, 'shared'); -</script> -<!-- -*/ -//--> -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/002.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/002.html deleted file mode 100644 index 9ab1f54f..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/002.html +++ /dev/null
@@ -1,28 +0,0 @@ -<!-- -postMessage(1); -/* ---> -<!doctype html> -<title>creating 3 sibling dedicated workers</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function(t) { - var w1 = new Worker('#'); - var w2 = new Worker('#'); - var w3 = new Worker('#'); - var got = [false, false, false]; - var check_done = t.step_func(function() { - if (got.every(function(x) {return x})) { - t.done(); - } - }); - w1.onmessage = t.step_func(function(e) {got[0] = true; check_done()}); - w2.onmessage = t.step_func(function(e) {got[1] = true; check_done()}); - w3.onmessage = t.step_func(function(e) {got[2] = true; check_done()}); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/003.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/003.html deleted file mode 100644 index 85c688bc..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/003.html +++ /dev/null
@@ -1,34 +0,0 @@ -<!-- -if (location.hash == '#1') { - var w2 = new Worker('#2'); - w2.onmessage = function(e) { - postMessage('1'+e.data); - } -} else if (location.hash == '#2') { - var w3 = new Worker('#3'); - w3.onmessage = function(e) { - postMessage('2'+e.data); - } -} else { - postMessage('3'); -} - -/* ---> -<!doctype html> -<title>creating 3 nested dedicated workers</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var w1 = new Worker('#1'); - w1.onmessage = this.step_func(function(e) { - assert_equals(e.data, '123'); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/004-2.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/004-2.js deleted file mode 100644 index e59cd692..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/004-2.js +++ /dev/null
@@ -1,6 +0,0 @@ -var port; -onconnect = function(e) { - if (!port) - port = e.ports[0]; - port.postMessage(1); -} \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/004.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/004.html deleted file mode 100644 index c473370..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/004.html +++ /dev/null
@@ -1,34 +0,0 @@ -<!doctype html> -<title>shared worker with multiple documents</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -var i = 0; -var load_count = 0; - -var w1 = new SharedWorker('004-2.js', 'x'); -w1.port.onmessage = function(e) { - i++; - check_result(); -}; - - -function iframe_loaded() { - load_count++; - check_result(); -} - -function check_result() { - //timeout to allow for extra, unexpected, messages to arrive - if (i == 3 && load_count == 2) { - setTimeout(function() { - assert_equals(load_count, 2); - assert_equals(i, 3); - done(); - }, 500); - } -} -</script> -<iframe src=004-1.html onload="iframe_loaded()"></iframe> -<iframe src=004-1.html onload="iframe_loaded()"></iframe>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/005.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/005.html deleted file mode 100644 index 289c25ec..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/005.html +++ /dev/null
@@ -1,37 +0,0 @@ -<!-- -if (location.hash == '#1') { - var w2 = new SharedWorker('#2'); - w2.port.onmessage = function(e) { - postMessage('1'+e.data); - } -} else if (location.hash == '#2') { - onconnect = function(e) { - var port = e.ports[0]; - var w3 = new Worker('#3'); - w3.onmessage = function(e) { - port.postMessage('2'+e.data); - } - } -} else { - postMessage('3'); -} - -/* ---> -<!doctype html> -<title>dedicated worker in shared worker in dedicated worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var w1 = new Worker('#1'); - w1.onmessage = this.step_func(function(e) { - assert_equals(e.data, '123'); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/006-1.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/006-1.js deleted file mode 100644 index 6c1ed93..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/006-1.js +++ /dev/null
@@ -1,3 +0,0 @@ - onconnect = function(e) { - e.ports[0].postMessage('3'); - } \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/006.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/006.html deleted file mode 100644 index ef212425..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/006.html +++ /dev/null
@@ -1,35 +0,0 @@ -<!-- -if (location.hash == '#1') { - onconnect = function(e) { - var port = e.ports[0]; - var w2 = new Worker('#2'); - w2.onmessage = function(e) { - port.postMessage('1'+e.data); - } - } -} else if (location.hash == '#2') { - var w3 = new SharedWorker('006-1.js'); - w3.port.onmessage = function(e) { - postMessage('2'+e.data); - } -} - -/* ---> -<!doctype html> -<title>shared worker in dedicated worker in shared worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var w1 = new SharedWorker('#1'); - w1.port.onmessage = this.step_func(function(e) { - assert_equals(e.data, '123'); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/007.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/007.html deleted file mode 100644 index e9934507..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/007.html +++ /dev/null
@@ -1,39 +0,0 @@ -<!-- -if (location.hash == '#1') { - onconnect = function(e) { - var port = e.ports[0]; - var w2 = new Worker('#2'); - w2.onmessage = function(e) { - port.postMessage('1'+e.data); - } - } -} else if (location.hash == '#2') { - var w3 = new SharedWorker('#3'); - w3.port.onmessage = function(e) { - postMessage('2'+e.data); - } -} else { - onconnect = function(e) { - e.ports[0].postMessage('3'); - } -} - -/* ---> -<!doctype html> -<title>shared worker in dedicated worker in shared worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var w1 = new SharedWorker('#1'); - w1.port.onmessage = this.step_func(function(e) { - assert_equals(e.data, '123'); - this.done(); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/008.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/008.html deleted file mode 100644 index fbb41e0d..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/008.html +++ /dev/null
@@ -1,31 +0,0 @@ -<!-- -var channel = new MessageChannel(); -var i = 0; -onconnect = function(e) { - i++; - e.ports[0].postMessage(1, [channel['port' + i]]); -} - -/* ---> -<!doctype html> -<title>messagechannel in shared worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<iframe src=008-1.html></iframe> -<script> -var t = async_test(); -onload = t.step_func(function() { - var w1 = new SharedWorker('#'); - w1.port.onmessage = this.step_func(function(e) { - e.ports[0].onmessage = this.step_func(function(e) { - assert_equals(e.data, 2); - this.done(); - }); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/navigation/001.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/navigation/001.html deleted file mode 100644 index 658df06..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/navigation/001.html +++ /dev/null
@@ -1,36 +0,0 @@ -<!-- - -/* ---> -<!doctype html> -<title>navigating</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -var date; -var newDate; -</script> -<iframe></iframe> -<script> -var iframe = document.querySelector('iframe'); -onload = function() { - iframe.src = "001-1.html?" + Math.random(); -}; -var start_test = function() { - window[0].document.links[0].click(); -}; -var after_load = function() { - history.back(); - newDate = new Date(); - setTimeout(function() { - assert_greater_than(Number(date), Number(newDate)); - assert_equals(window[0].document.title, '001-1'); - done(); - }, 2000); -}; -</script> -<!-- -*/ -//--> -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/navigation/002.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/navigation/002.html deleted file mode 100644 index c0d5eb5..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/navigation/002.html +++ /dev/null
@@ -1,36 +0,0 @@ -<!-- - -/* ---> -<!doctype html> -<title>navigating 2</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -var date; -var newDate; -</script> -<iframe></iframe> -<script> -var t = async_test(); -var iframe = document.querySelector('iframe'); -onload = t.step_func(function() { - iframe.src = "001-1.html?" + Math.random(); -}); -var start_test = t.step_func(function() { - window[0].document.links[0].click(); -}); -var after_load = t.step_func(function() { - newDate = new Date(); - setTimeout(this.step_func(function() { - assert_less_than(Number(date), Number(newDate)); - assert_equals(window[0].document.title, 'foo'); - this.done(); - }), 500); -}); -</script> -<!-- -*/ -//--> -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/001.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/001.html deleted file mode 100644 index adba81f..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/001.html +++ /dev/null
@@ -1,53 +0,0 @@ -<!-- -var port; -var timeout; -onerror = function(a,b,c,d,e) { - // will return undefined, thus the error is "not handled" - // so error should be reported to the user, but this test doesn't check - // that. - // just make sure that this method is invoked with five arguments - clearTimeout(timeout); - var log = ''; - if (arguments.length != 5) - log += 'got ' + arguments.length + ' arguments, expected 5. '; - if (typeof a != 'string') - log += 'first argument wasn\'t a string. '; - if (b != location.href) - log += 'second argument was ' + b + ', expected ' + location.href + '. '; - if (typeof c != 'number') - log += 'third argument wasn\'t a number. '; - if (typeof d != 'number') - log += 'fourth argument wasn\'t a number. '; - if (e != 42) - log += 'fifth argument wasn\'t the thrown exception. '; - port.postMessage(log); -} -onconnect = function (e) { - port = e.ports[0]; - timeout = setTimeout(function() { port.postMessage('self.onerror was not invoked'); }, 250); - throw 42; // will "report the error" -} - - -/* ---> -<!doctype html> -<title>shared worker, not handled</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -setup({allow_uncaught_exception:true}); -async_test(function() { - window.onerror = this.step_func(function(a) { - assert_unreached('window.onerror invoked: ' + a); - }); - var worker = new SharedWorker('#', ''); - worker.port.onmessage = this.step_func_done(function(e) { - assert_equals(e.data, ''); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/002.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/002.html deleted file mode 100644 index c2cd377..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/002.html +++ /dev/null
@@ -1,59 +0,0 @@ -<!-- -var port; -var timeout; -addEventListener('error', function(e) { - // event is not canceled, thus the error is "not handled" - // so error should be reported to the user, but this test doesn't check - // that. - // just make sure that this event has the right properties - clearTimeout(timeout); - var log = ''; - if (!self.ErrorEvent || Object.getPrototypeOf(e) != ErrorEvent.prototype) - log += 'event should be an ErrorEvent. '; - if (e.bubbles) - log += 'event should not bubble. '; - if (!e.cancelable) - log += 'event should be cancelable. '; - if (!e.isTrusted) - log += 'event should be trusted. '; - if (typeof e.message != 'string') - log += 'message wasn\'t a string. '; - if (e.filename != location.href) - log += 'filename was ' + e.filename + ', expected ' + location.href + '. '; - if (typeof e.lineno != 'number') - log += 'lineno wasn\'t a number. '; - if (typeof e.colno != 'number') - log += 'colno argument wasn\'t a number. '; - if (e.error != 42) - log += 'fifth argument wasn\'t the thrown exception. '; - port.postMessage(log); -}, false); -onconnect = function (e) { - port = e.ports[0]; - timeout = setTimeout(function() { port.postMessage('No error event fired'); }, 250); - throw 42; // will "report the error" -} - - -/* ---> -<!doctype html> -<title>shared worker, addEventListener</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -setup({allow_uncaught_exception:true}); -async_test(function() { - window.onerror = this.step_func(function(a) { - assert_unreached('window.onerror invoked: ' + a); - }); - var worker = new SharedWorker('#', ''); - worker.port.onmessage = this.step_func_done(function(e) { - assert_equals(e.data, ''); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/003.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/003.html deleted file mode 100644 index 1b01c7c..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/003.html +++ /dev/null
@@ -1,39 +0,0 @@ -<!-- -onconnect = function (e) { - setTimeout(function() { e.ports[0].postMessage(''); }, 250); - y(); // will "report the error" - // onerror is null so it'll be "not handled", and the error should be - // reported to the user, although we don't test that here - // make sure we don't fire an error event on the message port or the - // SharedWorker object -} - - -/* ---> -<!doctype html> -<title>shared worker, no error event on worker or port</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -setup({allow_uncaught_exception:true}); -async_test(function() { - window.onerror = this.step_func(function(a) { - assert_unreached('window.onerror invoked: ' + a); - }); - var worker = new SharedWorker('#', ''); - worker.addEventListener('error', this.step_func(function(e) { - assert_unreached('error on worker'); - }), false); - worker.port.addEventListener('error', this.step_func(function(e) { - assert_unreached('error on port'); - }), false); - worker.port.onmessage = this.step_func_done(function(e) { - assert_equals(e.data, ''); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/004.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/004.html deleted file mode 100644 index 1dd1eb3b..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/004.html +++ /dev/null
@@ -1,39 +0,0 @@ -<!-- -var i = 0; -onconnect = function (e) { - i++; - setTimeout(function() { e.ports[0].postMessage(i); }, 250); - y(); // will "report the error" -} - -/* ---> -<!doctype html> -<title>shared worker in two documents and window.onerror</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -setup({allow_uncaught_exception:true}); -var t = async_test(function() { - window.onerror = this.step_func(function(a) { - assert_unreached('(outer) window.onerror invoked: ' + a); - }); - var worker = new SharedWorker('#', ''); - worker.addEventListener('error', this.step_func(function(e) { - assert_unreached('(outer) error on worker'); - }), false); - worker.port.addEventListener('error', this.step_func(function(e) { - assert_unreached('(outer) error on port'); - }), false); - worker.port.onmessage = this.step_func(function(e) { - assert_equals(e.data, 1); - var iframe = document.createElement('iframe'); - iframe.src = '004-1.html'; - document.body.appendChild(iframe); - }); -}); -</script> -<!-- -*/ -//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/run-a-worker/001.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/run-a-worker/001.html deleted file mode 100644 index aa0fc67..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/run-a-worker/001.html +++ /dev/null
@@ -1,22 +0,0 @@ -<!-- -postMessage(this === self); - -/* ---> -<!doctype html> -<title>worker global scope, dedicated worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_true(e.data); - this.done(); - }); -}); -</script> -<!-- -*/ -//--> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/run-a-worker/002.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/run-a-worker/002.html deleted file mode 100644 index 3617ad72..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/run-a-worker/002.html +++ /dev/null
@@ -1,24 +0,0 @@ -<!-- -var passed = this === self; -onconnect = function(e) { - e.ports[0].postMessage(passed); -} -/* ---> -<!doctype html> -<title>worker global scope, shared worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -async_test(function() { - var worker = new SharedWorker('#'); - worker.port.onmessage = this.step_func(function(e) { - assert_true(e.data); - this.done(); - }); -}); -</script> -<!-- -*/ -//--> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/run-a-worker/003.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/run-a-worker/003.html deleted file mode 100644 index 8c2f07e..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/run-a-worker/003.html +++ /dev/null
@@ -1,21 +0,0 @@ -<!doctype html> -<title>handling for 404 response</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -setup({allow_uncaught_exception: true}); - -async_test(function() { - var worker = new Worker('404_worker'); - worker.onerror = this.step_func(function(e) { this.done(); }); -}, 'worker'); - -async_test(function() { - var shared = new SharedWorker('404_shared'); - // NOTE: this handler will not fire, as runtime scripting errors - // are not forwarded to SharedWorker objects, but instead reported to the user directly. - shared.onerror = this.step_func(function(e) { assert_unreached(); }, shared, 'error'); - step_timeout(this.step_func(function() { this.done(); }), 5000); -}, 'shared'); -</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/common.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/common.js deleted file mode 100644 index 56c2a30..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/common.js +++ /dev/null
@@ -1,596 +0,0 @@ -function createWorker(msg) { - // `type` is defined in the test case itself - if (type == 'dedicated') - return new Worker('dedicated.js#'+encodeURIComponent(msg)); - else if (type == 'shared') - return (new SharedWorker('shared.js#'+encodeURIComponent(msg))).port; - else - assert_unreached('invalid or missing `type`'); -} - -function check(msg, input, callback, test_obj) { - if (!test_obj) - test_obj = async_test(msg); - test_obj.step(function() { - var w = createWorker(msg); - if (typeof input === 'function') - input = this.step(input); - w.postMessage(input); - w.onmessage = this.step_func(function(ev) { callback(ev.data, input, this); }); - }); -} - -function compare_primitive(actual, input, test_obj) { - assert_equals(actual, input); - if (test_obj) - test_obj.done(); -} -function compare_Array(callback, callback_is_async) { - return function(actual, input, test_obj) { - if (typeof actual === 'string') - assert_unreached(actual); - assert_true(actual instanceof Array, 'instanceof Array'); - assert_not_equals(actual, input); - assert_equals(actual.length, input.length, 'length'); - callback(actual, input); - if (test_obj && !callback_is_async) - test_obj.done(); - } -} - -function compare_Object(callback, callback_is_async) { - return function(actual, input, test_obj) { - if (typeof actual === 'string') - assert_unreached(actual); - assert_true(actual instanceof Object, 'instanceof Object'); - assert_false(actual instanceof Array, 'instanceof Array'); - assert_not_equals(actual, input); - callback(actual, input); - if (test_obj && !callback_is_async) - test_obj.done(); - } -} - -function enumerate_props(compare_func, test_obj) { - return function(actual, input) { - for (var x in input) { - compare_func(actual[x], input[x], test_obj); - } - }; -} - -check('primitive undefined', undefined, compare_primitive); -check('primitive null', null, compare_primitive); -check('primitive true', true, compare_primitive); -check('primitive false', false, compare_primitive); -check('primitive string, empty string', '', compare_primitive); -check('primitive string, lone high surrogate', '\uD800', compare_primitive); -check('primitive string, lone low surrogate', '\uDC00', compare_primitive); -check('primitive string, NUL', '\u0000', compare_primitive); -check('primitive string, astral character', '\uDBFF\uDFFD', compare_primitive); -check('primitive number, 0.2', 0.2, compare_primitive); -check('primitive number, 0', 0, compare_primitive); -check('primitive number, -0', -0, compare_primitive); -check('primitive number, NaN', NaN, compare_primitive); -check('primitive number, Infinity', Infinity, compare_primitive); -check('primitive number, -Infinity', -Infinity, compare_primitive); -check('primitive number, 9007199254740992', 9007199254740992, compare_primitive); -check('primitive number, -9007199254740992', -9007199254740992, compare_primitive); -check('primitive number, 9007199254740994', 9007199254740994, compare_primitive); -check('primitive number, -9007199254740994', -9007199254740994, compare_primitive); - -check('Array primitives', [undefined, - null, - true, - false, - '', - '\uD800', - '\uDC00', - '\u0000', - '\uDBFF\uDFFD', - 0.2, - 0, - -0, - NaN, - Infinity, - -Infinity, - 9007199254740992, - -9007199254740992, - 9007199254740994, - -9007199254740994], compare_Array(enumerate_props(compare_primitive))); -check('Object primitives', {'undefined':undefined, - 'null':null, - 'true':true, - 'false':false, - 'empty':'', - 'high surrogate':'\uD800', - 'low surrogate':'\uDC00', - 'nul':'\u0000', - 'astral':'\uDBFF\uDFFD', - '0.2':0.2, - '0':0, - '-0':-0, - 'NaN':NaN, - 'Infinity':Infinity, - '-Infinity':-Infinity, - '9007199254740992':9007199254740992, - '-9007199254740992':-9007199254740992, - '9007199254740994':9007199254740994, - '-9007199254740994':-9007199254740994}, compare_Object(enumerate_props(compare_primitive))); - -function compare_Boolean(actual, input, test_obj) { - if (typeof actual === 'string') - assert_unreached(actual); - assert_true(actual instanceof Boolean, 'instanceof Boolean'); - assert_equals(String(actual), String(input), 'converted to primitive'); - assert_not_equals(actual, input); - if (test_obj) - test_obj.done(); -} -check('Boolean true', new Boolean(true), compare_Boolean); -check('Boolean false', new Boolean(false), compare_Boolean); -check('Array Boolean objects', [new Boolean(true), new Boolean(false)], compare_Array(enumerate_props(compare_Boolean))); -check('Object Boolean objects', {'true':new Boolean(true), 'false':new Boolean(false)}, compare_Object(enumerate_props(compare_Boolean))); - -function compare_obj(what) { - var Type = window[what]; - return function(actual, input, test_obj) { - if (typeof actual === 'string') - assert_unreached(actual); - assert_true(actual instanceof Type, 'instanceof '+what); - assert_equals(Type(actual), Type(input), 'converted to primitive'); - assert_not_equals(actual, input); - if (test_obj) - test_obj.done(); - }; -} -check('String empty string', new String(''), compare_obj('String')); -check('String lone high surrogate', new String('\uD800'), compare_obj('String')); -check('String lone low surrogate', new String('\uDC00'), compare_obj('String')); -check('String NUL', new String('\u0000'), compare_obj('String')); -check('String astral character', new String('\uDBFF\uDFFD'), compare_obj('String')); -check('Array String objects', [new String(''), - new String('\uD800'), - new String('\uDC00'), - new String('\u0000'), - new String('\uDBFF\uDFFD')], compare_Array(enumerate_props(compare_obj('String')))); -check('Object String objects', {'empty':new String(''), - 'high surrogate':new String('\uD800'), - 'low surrogate':new String('\uDC00'), - 'nul':new String('\u0000'), - 'astral':new String('\uDBFF\uDFFD')}, compare_Object(enumerate_props(compare_obj('String')))); - -check('Number 0.2', new Number(0.2), compare_obj('Number')); -check('Number 0', new Number(0), compare_obj('Number')); -check('Number -0', new Number(-0), compare_obj('Number')); -check('Number NaN', new Number(NaN), compare_obj('Number')); -check('Number Infinity', new Number(Infinity), compare_obj('Number')); -check('Number -Infinity', new Number(-Infinity), compare_obj('Number')); -check('Number 9007199254740992', new Number(9007199254740992), compare_obj('Number')); -check('Number -9007199254740992', new Number(-9007199254740992), compare_obj('Number')); -check('Number 9007199254740994', new Number(9007199254740994), compare_obj('Number')); -check('Number -9007199254740994', new Number(-9007199254740994), compare_obj('Number')); -check('Array Number objects', [new Number(0.2), - new Number(0), - new Number(-0), - new Number(NaN), - new Number(Infinity), - new Number(-Infinity), - new Number(9007199254740992), - new Number(-9007199254740992), - new Number(9007199254740994), - new Number(-9007199254740994)], compare_Array(enumerate_props(compare_obj('Number')))); -check('Object Number objects', {'0.2':new Number(0.2), - '0':new Number(0), - '-0':new Number(-0), - 'NaN':new Number(NaN), - 'Infinity':new Number(Infinity), - '-Infinity':new Number(-Infinity), - '9007199254740992':new Number(9007199254740992), - '-9007199254740992':new Number(-9007199254740992), - '9007199254740994':new Number(9007199254740994), - '-9007199254740994':new Number(-9007199254740994)}, compare_Object(enumerate_props(compare_obj('Number')))); - -function compare_Date(actual, input, test_obj) { - if (typeof actual === 'string') - assert_unreached(actual); - assert_true(actual instanceof Date, 'instanceof Date'); - assert_equals(Number(actual), Number(input), 'converted to primitive'); - assert_not_equals(actual, input); - if (test_obj) - test_obj.done(); -} -check('Date 0', new Date(0), compare_Date); -check('Date -0', new Date(-0), compare_Date); -check('Date -8.64e15', new Date(-8.64e15), compare_Date); -check('Date 8.64e15', new Date(8.64e15), compare_Date); -check('Array Date objects', [new Date(0), - new Date(-0), - new Date(-8.64e15), - new Date(8.64e15)], compare_Array(enumerate_props(compare_Date))); -check('Object Date objects', {'0':new Date(0), - '-0':new Date(-0), - '-8.64e15':new Date(-8.64e15), - '8.64e15':new Date(8.64e15)}, compare_Object(enumerate_props(compare_Date))); - -function compare_RegExp(expected_source) { - // XXX ES6 spec doesn't define exact serialization for `source` (it allows several ways to escape) - return function(actual, input, test_obj) { - if (typeof actual === 'string') - assert_unreached(actual); - assert_true(actual instanceof RegExp, 'instanceof RegExp'); - assert_equals(actual.global, input.global, 'global'); - assert_equals(actual.ignoreCase, input.ignoreCase, 'ignoreCase'); - assert_equals(actual.multiline, input.multiline, 'multiline'); - assert_equals(actual.source, expected_source, 'source'); - assert_equals(actual.sticky, input.sticky, 'sticky'); - assert_equals(actual.unicode, input.unicode, 'unicode'); - assert_equals(actual.lastIndex, 0, 'lastIndex'); - assert_not_equals(actual, input); - if (test_obj) - test_obj.done(); - } -} -function func_RegExp_flags_lastIndex() { - var r = /foo/gim; - r.lastIndex = 2; - return r; -} -function func_RegExp_sticky() { - return new RegExp('foo', 'y'); -} -function func_RegExp_unicode() { - return new RegExp('foo', 'u'); -} -check('RegExp flags and lastIndex', func_RegExp_flags_lastIndex, compare_RegExp('foo')); -check('RegExp sticky flag', func_RegExp_sticky, compare_RegExp('foo')); -check('RegExp unicode flag', func_RegExp_unicode, compare_RegExp('foo')); -check('RegExp empty', new RegExp(''), compare_RegExp('(?:)')); -check('RegExp slash', new RegExp('/'), compare_RegExp('\\/')); -check('RegExp new line', new RegExp('\n'), compare_RegExp('\\n')); -check('Array RegExp object, RegExp flags and lastIndex', [func_RegExp_flags_lastIndex()], compare_Array(enumerate_props(compare_RegExp('foo')))); -check('Array RegExp object, RegExp sticky flag', function() { return [func_RegExp_sticky()]; }, compare_Array(enumerate_props(compare_RegExp('foo')))); -check('Array RegExp object, RegExp unicode flag', function() { return [func_RegExp_unicode()]; }, compare_Array(enumerate_props(compare_RegExp('foo')))); -check('Array RegExp object, RegExp empty', [new RegExp('')], compare_Array(enumerate_props(compare_RegExp('(?:)')))); -check('Array RegExp object, RegExp slash', [new RegExp('/')], compare_Array(enumerate_props(compare_RegExp('\\/')))); -check('Array RegExp object, RegExp new line', [new RegExp('\n')], compare_Array(enumerate_props(compare_RegExp('\\n')))); -check('Object RegExp object, RegExp flags and lastIndex', {'x':func_RegExp_flags_lastIndex()}, compare_Object(enumerate_props(compare_RegExp('foo')))); -check('Object RegExp object, RegExp sticky flag', function() { return {'x':func_RegExp_sticky()}; }, compare_Object(enumerate_props(compare_RegExp('foo')))); -check('Object RegExp object, RegExp unicode flag', function() { return {'x':func_RegExp_unicode()}; }, compare_Object(enumerate_props(compare_RegExp('foo')))); -check('Object RegExp object, RegExp empty', {'x':new RegExp('')}, compare_Object(enumerate_props(compare_RegExp('(?:)')))); -check('Object RegExp object, RegExp slash', {'x':new RegExp('/')}, compare_Object(enumerate_props(compare_RegExp('\\/')))); -check('Object RegExp object, RegExp new line', {'x':new RegExp('\n')}, compare_Object(enumerate_props(compare_RegExp('\\n')))); - -function compare_Blob(actual, input, test_obj, expect_File) { - if (typeof actual === 'string') - assert_unreached(actual); - assert_true(actual instanceof Blob, 'instanceof Blob'); - if (!expect_File) - assert_false(actual instanceof File, 'instanceof File'); - assert_equals(actual.size, input.size, 'size'); - assert_equals(actual.type, input.type, 'type'); - assert_not_equals(actual, input); - var ev_reader = new FileReader(); - var input_reader = new FileReader(); - var read_count = 0; - var read_done = test_obj.step_func(function() { - read_count++; - if (read_count == 2) { - var ev_result = ev_reader.result; - var input_result = input_reader.result; - assert_equals(ev_result.byteLength, input_result.byteLength, 'byteLength'); - var ev_view = new DataView(ev_result); - var input_view = new DataView(input_result); - for (var i = 0; i < ev_result.byteLength; ++i) { - assert_equals(ev_view.getUint8(i), input_view.getUint8(i), 'getUint8('+i+')'); - } - if (test_obj) - test_obj.done(); - } - }); - var read_error = test_obj.step_func(function() { assert_unreached('FileReader error'); }); - ev_reader.readAsArrayBuffer(actual); - ev_reader.onload = read_done; - ev_reader.onabort = ev_reader.onerror = read_error; - input_reader.readAsArrayBuffer(input); - input_reader.onload = read_done; - input_reader.onabort = input_reader.onerror = read_error; -} -function func_Blob_basic() { - return new Blob(['foo'], {type:'text/x-bar'}); -} -check('Blob basic', func_Blob_basic, compare_Blob); - -function b(str) { - return parseInt(str, 2); -} -function encode_cesu8(codeunits) { - // http://www.unicode.org/reports/tr26/ section 2.2 - // only the 3-byte form is supported - var rv = []; - codeunits.forEach(function(codeunit) { - rv.push(b('11100000') + ((codeunit & b('1111000000000000')) >> 12)); - rv.push(b('10000000') + ((codeunit & b('0000111111000000')) >> 6)); - rv.push(b('10000000') + (codeunit & b('0000000000111111'))); - }); - return rv; -} -function func_Blob_bytes(arr) { - return function() { - var buffer = new ArrayBuffer(arr.length); - var view = new DataView(buffer); - for (var i = 0; i < arr.length; ++i) { - view.setUint8(i, arr[i]); - } - return new Blob([view]); - }; -} -check('Blob unpaired high surrogate (invalid utf-8)', func_Blob_bytes(encode_cesu8([0xD800])), compare_Blob); -check('Blob unpaired low surrogate (invalid utf-8)', func_Blob_bytes(encode_cesu8([0xDC00])), compare_Blob); -check('Blob paired surrogates (invalid utf-8)', func_Blob_bytes(encode_cesu8([0xD800, 0xDC00])), compare_Blob); - -function func_Blob_empty() { - return new Blob(['']); -} -check('Blob empty', func_Blob_empty , compare_Blob); -function func_Blob_NUL() { - return new Blob(['\u0000']); -} -check('Blob NUL', func_Blob_NUL, compare_Blob); - -async_test(function(test_obj) { - check(test_obj.name, [test_obj.step(func_Blob_basic)], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj); -}, 'Array Blob object, Blob basic'); -async_test(function(test_obj) { - check(test_obj.name, [test_obj.step(func_Blob_bytes([0xD800]))], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj); -}, 'Array Blob object, Blob unpaired high surrogate (invalid utf-8)'); -async_test(function(test_obj) { - check(test_obj.name, [test_obj.step(func_Blob_bytes([0xDC00]))], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj); -}, 'Array Blob object, Blob unpaired low surrogate (invalid utf-8)'); -async_test(function(test_obj) { - check(test_obj.name, [test_obj.step(func_Blob_bytes([0xD800, 0xDC00]))], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj); -}, 'Array Blob object, Blob paired surrogates (invalid utf-8)'); -async_test(function(test_obj) { - check(test_obj.name, [test_obj.step(func_Blob_empty)], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj); -}, 'Array Blob object, Blob empty'); -async_test(function(test_obj) { - check(test_obj.name, [test_obj.step(func_Blob_NUL)], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj); -}, 'Array Blob object, Blob NUL'); - -async_test(function(test_obj) { - check(test_obj.name, {'x':test_obj.step(func_Blob_basic)}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj); -}, 'Object Blob object, Blob basic'); -async_test(function(test_obj) { - check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xD800]))}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj); -}, 'Object Blob object, Blob unpaired high surrogate (invalid utf-8)'); -async_test(function(test_obj) { - check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xDC00]))}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj); -}, 'Object Blob object, Blob unpaired low surrogate (invalid utf-8)'); -async_test(function(test_obj) { - check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xD800, 0xDC00]))}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj); -}, 'Object Blob object, Blob paired surrogates (invalid utf-8)'); -async_test(function(test_obj) { - check(test_obj.name, {'x':test_obj.step(func_Blob_empty)}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj); -}, 'Object Blob object, Blob empty'); -async_test(function(test_obj) { - check(test_obj.name, {'x':test_obj.step(func_Blob_NUL)}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj); -}, 'Object Blob object, Blob NUL'); - -function compare_File(actual, input, test_obj) { - assert_true(actual instanceof File, 'instanceof File'); - assert_equals(actual.name, input.name, 'name'); - assert_equals(actual.lastModified, input.lastModified, 'lastModified'); - compare_Blob(actual, input, test_obj, true); -} -function func_File_basic() { - return new File(['foo'], 'bar', {type:'text/x-bar', lastModified:42}); -} -check('File basic', func_File_basic, compare_File); - -function compare_FileList(actual, input, test_obj) { - if (typeof actual === 'string') - assert_unreached(actual); - assert_true(actual instanceof FileList, 'instanceof FileList'); - assert_equals(actual.length, input.length, 'length'); - assert_not_equals(actual, input); - // XXX when there's a way to populate or construct a FileList, - // check the items in the FileList - if (test_obj) - test_obj.done(); -} -function func_FileList_empty() { - var input = document.createElement('input'); - input.type = 'file'; - return input.files; -} -check('FileList empty', func_FileList_empty, compare_FileList); -check('Array FileList object, FileList empty', [func_FileList_empty], compare_Array(enumerate_props(compare_FileList))); -check('Object FileList object, FileList empty', {'x':func_FileList_empty}, compare_Object(enumerate_props(compare_FileList))); - -function compare_ArrayBufferView(view) { - var Type = window[view]; - return function(actual, input, test_obj) { - if (typeof actual === 'string') - assert_unreached(actual); - assert_true(actual instanceof Type, 'instanceof '+view); - assert_equals(actual.length, input.length, 'length'); - assert_not_equals(actual.buffer, input.buffer, 'buffer'); - for (var i = 0; i < actual.length; ++i) { - assert_equals(actual[i], input[i], 'actual['+i+']'); - } - if (test_obj) - test_obj.done(); - }; -} -function compare_ImageData(actual, input, test_obj) { - if (typeof actual === 'string') - assert_unreached(actual); - assert_equals(actual.width, input.width, 'width'); - assert_equals(actual.height, input.height, 'height'); - assert_not_equals(actual.data, input.data, 'data'); - compare_ArrayBufferView('Uint8ClampedArray')(actual.data, input.data, null); - if (test_obj) - test_obj.done(); -} -function func_ImageData_1x1_transparent_black() { - var canvas = document.createElement('canvas'); - var ctx = canvas.getContext('2d'); - return ctx.createImageData(1, 1); -} -check('ImageData 1x1 transparent black', func_ImageData_1x1_transparent_black, compare_ImageData); -function func_ImageData_1x1_non_transparent_non_black() { - var canvas = document.createElement('canvas'); - var ctx = canvas.getContext('2d'); - var imagedata = ctx.createImageData(1, 1); - imagedata.data[0] = 100; - imagedata.data[1] = 101; - imagedata.data[2] = 102; - imagedata.data[3] = 103; - return imagedata; -} -check('ImageData 1x1 non-transparent non-black', func_ImageData_1x1_non_transparent_non_black, compare_ImageData); -async_test(function(test_obj) { - check(test_obj.name, [test_obj.step(func_ImageData_1x1_transparent_black)], compare_Array(enumerate_props(compare_ImageData)), test_obj); -}, 'Array ImageData object, ImageData 1x1 transparent black'); -async_test(function(test_obj) { - check(test_obj.name, [test_obj.step(func_ImageData_1x1_non_transparent_non_black)], compare_Array(enumerate_props(compare_ImageData)), test_obj); -}, 'Array ImageData object, ImageData 1x1 non-transparent non-black'); -async_test(function(test_obj) { - check(test_obj.name, {'x':test_obj.step(func_ImageData_1x1_transparent_black)}, compare_Object(enumerate_props(compare_ImageData)), test_obj); -}, 'Object ImageData object, ImageData 1x1 transparent black'); -async_test(function(test_obj) { - check(test_obj.name, {'x':test_obj.step(func_ImageData_1x1_non_transparent_non_black)}, compare_Object(enumerate_props(compare_ImageData)), test_obj); -}, 'Object ImageData object, ImageData 1x1 non-transparent non-black'); - -function compare_ImageBitmap(actual, input, test_obj) { - if (typeof actual === 'string') - assert_unreached(actual); - assert_equals(actual instanceof ImageBitmap, 'instanceof ImageBitmap'); - assert_not_equals(actual, input); - // XXX paint the ImageBitmap on a canvas and check the data - if (test_obj) - test_obj.done(); -} -function get_canvas_1x1_transparent_black() { - var canvas = document.createElement('canvas'); - canvas.width = 1; - canvas.height = 1; - return canvas; -} -async_test(function(test_obj) { - var canvas = get_canvas_1x1_transparent_black(); - createImageBitmap(canvas, function(image) { check(test_obj.name, image, compare_ImageBitmap, test_obj); }); -}, 'ImageBitmap 1x1 transparent black'); -function get_canvas_1x1_non_transparent_non_black() { - var canvas = document.createElement('canvas'); - canvas.width = 1; - canvas.height = 1; - var ctx = canvas.getContext('2d'); - var imagedata = ctx.getImageData(0, 0, 1, 1); - imagedata.data[0] = 100; - imagedata.data[1] = 101; - imagedata.data[2] = 102; - imagedata.data[3] = 103; - return canvas; -} -async_test(function(test_obj) { - var canvas = get_canvas_1x1_non_transparent_non_black(); - createImageBitmap(canvas, function(image) { check(test_obj.name, image, compare_ImageBitmap, test_obj); }); -}, 'ImageBitmap 1x1 non-transparent non-black'); - -async_test(function(test_obj) { - var canvas = get_canvas_1x1_transparent_black(); - createImageBitmap(canvas, function(image) { check(test_obj.name, [image], compare_Array(enumerate_props(compare_ImageBitmap)), test_obj); }); -}, 'Array ImageBitmap object, ImageBitmap 1x1 transparent black'); -async_test(function(test_obj) { - var canvas = get_canvas_1x1_non_transparent_non_black(); - createImageBitmap(canvas, function(image) { check(test_obj.name, [image], compare_Array(enumerate_props(compare_ImageBitmap)), test_obj); }); -}, 'Array ImageBitmap object, ImageBitmap 1x1 non-transparent non-black'); - -async_test(function(test_obj) { - var canvas = get_canvas_1x1_transparent_black(); - createImageBitmap(canvas, function(image) { check(test_obj.name, {'x':image}, compare_Object(enumerate_props(compare_ImageBitmap)), test_obj); }); -}, 'Object ImageBitmap object, ImageBitmap 1x1 transparent black'); -async_test(function(test_obj) { - var canvas = get_canvas_1x1_non_transparent_non_black(); - createImageBitmap(canvas, function(image) { check(test_obj.name, {'x':image}, compare_Object(enumerate_props(compare_ImageBitmap)), test_obj); }); -}, 'Object ImageBitmap object, ImageBitmap 1x1 non-transparent non-black'); - -check('Array sparse', new Array(10), compare_Array(enumerate_props(compare_primitive))); -check('Array with non-index property', function() { - var rv = []; - rv.foo = 'bar'; - return rv; -}, compare_Array(enumerate_props(compare_primitive))); -check('Object with index property and length', {'0':'foo', 'length':1}, compare_Object(enumerate_props(compare_primitive))); -function check_circular_property(prop) { - return function(actual) { - assert_equals(actual[prop], actual); - }; -} -check('Array with circular reference', function() { - var rv = []; - rv[0] = rv; - return rv; -}, compare_Array(check_circular_property('0'))); -check('Object with circular reference', function() { - var rv = {}; - rv['x'] = rv; - return rv; -}, compare_Object(check_circular_property('x'))); -function check_identical_property_values(prop1, prop2) { - return function(actual) { - assert_equals(actual[prop1], actual[prop2]); - }; -} -check('Array with identical property values', function() { - var obj = {} - return [obj, obj]; -}, compare_Array(check_identical_property_values('0', '1'))); -check('Object with identical property values', function() { - var obj = {} - return {'x':obj, 'y':obj}; -}, compare_Object(check_identical_property_values('x', 'y'))); - -function check_absent_property(prop) { - return function(actual) { - assert_false(prop in actual); - }; -} -check('Object with property on prototype', function() { - var Foo = function() {}; - Foo.prototype = {'foo':'bar'}; - return new Foo(); -}, compare_Object(check_absent_property('foo'))); - -check('Object with non-enumerable property', function() { - var rv = {}; - Object.defineProperty(rv, 'foo', {value:'bar', enumerable:false, writable:true, configurable:true}); - return rv; -}, compare_Object(check_absent_property('foo'))); - -function check_writable_property(prop) { - return function(actual, input) { - assert_equals(actual[prop], input[prop]); - actual[prop] += ' baz'; - assert_equals(actual[prop], input[prop] + ' baz'); - }; -} -check('Object with non-writable property', function() { - var rv = {}; - Object.defineProperty(rv, 'foo', {value:'bar', enumerable:true, writable:false, configurable:true}); - return rv; -}, compare_Object(check_writable_property('foo'))); - -function check_configurable_property(prop) { - return function(actual, input) { - assert_equals(actual[prop], input[prop]); - delete actual[prop]; - assert_false('prop' in actual); - }; -} -check('Object with non-configurable property', function() { - var rv = {}; - Object.defineProperty(rv, 'foo', {value:'bar', enumerable:true, writable:true, configurable:false}); - return rv; -}, compare_Object(check_configurable_property('foo')));
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/dedicated.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/dedicated.html deleted file mode 100644 index 5dd8c356..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/dedicated.html +++ /dev/null
@@ -1,9 +0,0 @@ -<!doctype html> -<title>structured clone to dedicated worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -var type = 'dedicated'; -</script> -<script src="common.js"></script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/dedicated.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/dedicated.js deleted file mode 100644 index 4744578..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/dedicated.js +++ /dev/null
@@ -1,4 +0,0 @@ -importScripts('worker-common.js'); -onmessage = function(ev) { - check(ev.data, self); -};
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/shared.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/shared.html deleted file mode 100644 index 6f74354..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/shared.html +++ /dev/null
@@ -1,9 +0,0 @@ -<!doctype html> -<title>structured clone to shared worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -var type = 'shared'; -</script> -<script src="common.js"></script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/shared.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/shared.js deleted file mode 100644 index 372a9ec9..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/shared.js +++ /dev/null
@@ -1,6 +0,0 @@ -importScripts('worker-common.js'); -onconnect = function(connect_ev) { - connect_ev.ports[0].onmessage = function(message_ev) { - check(message_ev.data, this); - }; -};
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/worker-common.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/worker-common.js deleted file mode 100644 index fd63ff5..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/worker-common.js +++ /dev/null
@@ -1,1018 +0,0 @@ -var msg = decodeURIComponent(location.hash.substr(1)); - -var log = []; -function check_true(actual, msg) { - if (actual !== true) { - log.push(msg); - return false; - } - return true; -} - -function check_Blob(msg, input, port, expect_File, orig_input) { - expect_File = !!expect_File; - orig_input = orig_input || input; - try { - var expected; - switch (msg) { - case 'Blob basic': - case 'File basic': - expected = [0x66, 0x6F, 0x6F]; - expected.type = 'text/x-bar'; - if (expect_File) { - expected.name = 'bar'; - expected.lastModified = 42; - } - break; - case 'Blob unpaired high surrogate (invalid utf-8)': - expected = [0xED, 0xA0, 0x80]; - expected.type = ''; - break; - case 'Blob unpaired low surrogate (invalid utf-8)': - expected = [0xED, 0xB0, 0x80]; - expected.type = ''; - break; - case 'Blob paired surrogates (invalid utf-8)': - expected = [0xED, 0xA0, 0x80, 0xED, 0xB0, 0x80]; - expected.type = ''; - break; - case 'Blob empty': - expected = []; - expected.type = ''; - break; - case 'Blob NUL': - var expected = [0x00]; - expected.type = ''; - break; - default: - check_true(false, 'check_Blob: unknown test'); - return; - break; - } - if (check_true(input instanceof Blob, 'input instanceof Blob') && - check_true((input instanceof File) == expect_File, '(input instanceof File) == expect_File') && - check_true(input.size === expected.length, 'input.size === expected.length') && - check_true(input.type === expected.type, 'input.type === expected.type')) { - if (!expect_File || (check_true(input.name === expected.name, 'input.name === expected.name') && - check_true(input.lastModified === expected.lastModified))) { - var reader = new FileReader(); - var read_done = function() { - try { - var result = reader.result; - check_true(result.byteLength === expected.length, 'result.byteLength === expected.length') - var view = new DataView(result); - for (var i = 0; i < result.byteLength; ++i) { - check_true(view.getUint8(i) === expected[i], 'view.getUint8('+i+') === expected['+i+']') - } - if (log.length === 0) { - port.postMessage(orig_input); - } else { - port.postMessage('FAIL '+log); - } - close(); - } catch(ex) { - postMessage('FAIL '+ex); - close(); - } - } - var read_error = function() { port.postMessage('FAIL (got FileReader error)'); close(); }; - reader.readAsArrayBuffer(input); - reader.onload = read_done; - reader.onabort = reader.onerror = read_error; - } - } else { - port.postMessage('FAIL '+log); - close(); - } - } catch(ex) { - postMessage('FAIL '+ex); - close(); - } -} - -function check_ImageData(input, expected) { - if (check_true(input instanceof ImageData, 'input instanceof ImageData') && - check_true(input.width === expected.width, 'input.width === '+expected.width) && - check_true(input.height === expected.height, 'input.height === '+expected.height) && - check_true(input.data instanceof Uint8ClampedArray, 'input.data instanceof Uint8ClampedArray') && - check_true(input.data.length === expected.data.length, 'input.data.length === '+expected.data.length) && - check_true(!('CanvasPixelArray' in self), "!('CanvasPixelArray' in self)")) { - for (var i = 0; i < input.length; ++i) { - if (!(check_true(input.data[i] === expected.data[i], 'input.data['+i+'] === '+expected.data[i]))) { - return false; - } - } - return true; - } - return false; -} - -function check_ImageBitmap(input, expected) { - return check_true(input instanceof ImageBitmap, 'input instanceof ImageBitmap'); - // XXX paint it on a proxy canvas and check the data -} - -function check_RegExp(msg, input) { - // XXX ES6 spec doesn't define exact serialization for `source` (it allows several ways to escape) - switch (msg) { - case 'RegExp flags and lastIndex': - return check_true(input instanceof RegExp, "input instanceof RegExp") && - check_true(input.source === 'foo', "input.source === 'foo'") && - check_true(input.global === true, "input.global === true") && - check_true(input.ignoreCase === true, "input.ignoreCase === true") && - check_true(input.multiline === true, "input.multiline === true") && - check_true(input.lastIndex === 0, "input.lastIndex === 0"); - break; - case 'RegExp sticky flag': - return check_true(input instanceof RegExp, "input instanceof RegExp") && - check_true(input.source === 'foo', "input.source === 'foo'") && - check_true(input.global === false, "input.global === false") && - check_true(input.ignoreCase === false, "input.ignoreCase === false") && - check_true(input.multiline === false, "input.multiline === false") && - check_true(input.sticky === true, "input.sticky === true") && - check_true(input.unicode === false, "input.unicode === false") && - check_true(input.lastIndex === 0, "input.lastIndex === 0"); - break; - case 'RegExp unicode flag': - return check_true(input instanceof RegExp, "input instanceof RegExp") && - check_true(input.source === 'foo', "input.source === 'foo'") && - check_true(input.global === false, "input.global === false") && - check_true(input.ignoreCase === false, "input.ignoreCase === false") && - check_true(input.multiline === false, "input.multiline === false") && - check_true(input.sticky === false, "input.sticky === false") && - check_true(input.unicode === true, "input.unicode === true") && - check_true(input.lastIndex === 0, "input.lastIndex === 0"); - break; - case 'RegExp empty': - return check_true(input instanceof RegExp, "input instanceof RegExp") && - check_true(input.source === '(?:)', "input.source === '(?:)'") && - check_true(input.global === false, "input.global === false") && - check_true(input.ignoreCase === false, "input.ignoreCase === false") && - check_true(input.multiline === false, "input.multiline === false") && - check_true(input.lastIndex === 0, "input.lastIndex === 0"); - break; - case 'RegExp slash': - return check_true(input instanceof RegExp, "input instanceof RegExp") && - check_true(input.source === '\\/', "input.source === '\\\\/'") && - check_true(input.global === false, "input.global === false") && - check_true(input.ignoreCase === false, "input.ignoreCase === false") && - check_true(input.multiline === false, "input.multiline === false") && - check_true(input.lastIndex === 0, "input.lastIndex === 0"); - break; - case 'RegExp new line': - return check_true(input instanceof RegExp, "input instanceof RegExp") && - check_true(input.source === '\\n', "input.source === '\\\\n'") && - check_true(input.global === false, "input.global === false") && - check_true(input.ignoreCase === false, "input.ignoreCase === false") && - check_true(input.multiline === false, "input.multiline === false") && - check_true(input.lastIndex === 0, "input.lastIndex === 0"); - break; - default: - check_true(false, 'check_RegExp: unknown test'); - return false; - break; - } -} - -function check_FileList(msg, input) { - try { - return check_true(input instanceof FileList, 'input instanceof FileList') && - check_true(input.length === 0, 'input.length === 0'); - } catch(ex) { - return check_true(false, ex); - } -} - -function check(input, port) { - try { - switch (msg) { - case 'primitive undefined': - if (check_true(input === undefined, 'input === undefined')) { - port.postMessage(input); - close(); - } - break; - case 'primitive null': - if (check_true(input === null, 'input === null')) { - port.postMessage(input); - close(); - } - break; - case 'primitive true': - if (check_true(input === true, 'input === true')) { - port.postMessage(input); - close(); - } - break; - case 'primitive false': - if (check_true(input === false, 'input === false')) { - port.postMessage(input); - close(); - } - break; - case 'primitive string, empty string': - if (check_true(input === '', "input === ''")) { - port.postMessage(input); - close(); - } - break; - case 'primitive string, lone high surrogate': - if (check_true(input === '\uD800', "input === '\uD800'")) { - port.postMessage(input); - close(); - } - break; - case 'primitive string, lone low surrogate': - if (check_true(input === '\uDC00', "input === '\uDC00'")) { - port.postMessage(input); - close(); - } - break; - case 'primitive string, NUL': - if (check_true(input === '\u0000', "input === '\u0000'")) { - port.postMessage(input); - close(); - } - break; - case 'primitive string, astral character': - if (check_true(input === '\uDBFF\uDFFD', "input === '\uDBFF\uDFFD'")) { - port.postMessage(input); - close(); - } - break; - case 'primitive number, 0.2': - if (check_true(input === 0.2, "input === 0.2")) { - port.postMessage(input); - close(); - } - break; - case 'primitive number, 0': - if (check_true(input === 0, "input === 0") && - check_true(1/input === Infinity, "1/input === Infinity")) { - port.postMessage(input); - close(); - } - break; - case 'primitive number, -0': - if (check_true(input === 0, "input === 0") && - check_true(1/input === -Infinity, "1/input === -Infinity")) { - port.postMessage(input); - close(); - } - break; - case 'primitive number, NaN': - if (check_true(input !== input, "input !== input")) { - port.postMessage(input); - close(); - } - break; - case 'primitive number, Infinity': - if (check_true(input === Infinity, "input === Infinity")) { - port.postMessage(input); - close(); - } - break; - case 'primitive number, -Infinity': - if (check_true(input === -Infinity, "input === -Infinity")) { - port.postMessage(input); - close(); - } - break; - case 'primitive number, 9007199254740992': - if (check_true(input === 9007199254740992, "input === 9007199254740992")) { - port.postMessage(input); - close(); - } - break; - case 'primitive number, -9007199254740992': - if (check_true(input === -9007199254740992, "input === -9007199254740992")) { - port.postMessage(input); - close(); - } - break; - case 'primitive number, 9007199254740994': - if (check_true(input === 9007199254740994, "input === 9007199254740994")) { - port.postMessage(input); - close(); - } - break; - case 'primitive number, -9007199254740994': - if (check_true(input === -9007199254740994, "input === -9007199254740994")) { - port.postMessage(input); - close(); - break; - } - case 'Array primitives': - if (check_true(input instanceof Array, 'input instanceof Array') && - check_true(input.length === 19, 'input.length === 19') && - check_true(input[0] === undefined, 'input[0] === undefined') && - check_true(input[1] === null, 'input[1] === null') && - check_true(input[2] === true, 'input[2] === true') && - check_true(input[3] === false, 'input[3] === false') && - check_true(input[4] === '', "input[4] === ''") && - check_true(input[5] === '\uD800', "input[5] === '\\uD800'") && - check_true(input[6] === '\uDC00', "input[6] === '\\uDC00'") && - check_true(input[7] === '\u0000', "input[7] === '\\u0000'") && - check_true(input[8] === '\uDBFF\uDFFD', "input[8] === '\\uDBFF\\uDFFD'") && - check_true(input[9] === 0.2, "input[9] === 0.2") && - check_true(1/input[10] === Infinity, "1/input[10] === Infinity") && - check_true(1/input[11] === -Infinity, "1/input[11] === -Infinity") && - check_true(input[12] !== input[11], "input[12] !== input[11]") && - check_true(input[13] === Infinity, "input[13] === Infinity") && - check_true(input[14] === -Infinity, "input[14] === -Infinity") && - check_true(input[15] === 9007199254740992, "input[15] === 9007199254740992") && - check_true(input[16] === -9007199254740992, "input[16] === -9007199254740992") && - check_true(input[17] === 9007199254740994, "input[17] === 9007199254740994") && - check_true(input[18] === -9007199254740994, "input[18] === -9007199254740994")) { - port.postMessage(input); - close(); - } - break; - case 'Object primitives': - (function() { - if (check_true(input instanceof Object, 'input instanceof Object') && - check_true(!(input instanceof Array), '!(input instanceof Array)') && - check_true(input['undefined'] === undefined, "input['undefined'] === undefined") && - check_true(input['null'] === null, "input['null'] === null") && - check_true(input['true'] === true, "input['true'] === true") && - check_true(input['false'] === false, "input['false'] === false") && - check_true(input['empty'] === '', "input['empty'] === ''") && - check_true(input['high surrogate'] === '\uD800', "input['high surrogate'] === '\uD800'") && - check_true(input['low surrogate'] === '\uDC00', "input['low surrogate'] === '\uDC00'") && - check_true(input['nul'] === '\u0000', "input['nul'] === '\u0000'") && - check_true(input['astral'] === '\uDBFF\uDFFD', "input['astral'] === '\uDBFF\uDFFD'") && - check_true(input['0.2'] === 0.2, "input['0.2'] === 0.2") && - check_true(1/input['0'] === Infinity, "1/input['0'] === Infinity") && - check_true(1/input['-0'] === -Infinity, "1/input['-0'] === -Infinity") && - check_true(input['NaN'] !== input['NaN'], "input['NaN'] !== input['NaN']") && - check_true(input['Infinity'] === Infinity, "input['Infinity'] === Infinity") && - check_true(input['-Infinity'] === -Infinity, "input['-Infinity'] === -Infinity") && - check_true(input['9007199254740992'] === 9007199254740992, "input['9007199254740992'] === 9007199254740992") && - check_true(input['-9007199254740992'] === -9007199254740992, "input['-9007199254740992'] === -9007199254740992") && - check_true(input['9007199254740994'] === 9007199254740994, "input['9007199254740994'] === 9007199254740994") && - check_true(input['-9007199254740994'] === -9007199254740994, "input['9007199254740994'] === -9007199254740994")) { - var i = 0; - for (var x in input) { - i++; - } - if (check_true(i === 19, 'i === 19')) { - port.postMessage(input); - close(); - } - } - })(); - break; - case 'Boolean true': - if (check_true(input instanceof Boolean, "input instanceof Boolean") && - check_true(String(input) === 'true', "String(input) === 'true'")) { - port.postMessage(input); - close(); - } - break; - case 'Boolean false': - if (check_true(input instanceof Boolean, "input instanceof Boolean") && - check_true(String(input) === 'false', "String(input) === 'false'")) { - port.postMessage(input); - close(); - } - break; - case 'Array Boolean objects': - (function() { - if (check_true(input instanceof Array, 'input instanceof Array') && - check_true(input.length === 2, 'input.length === 2') && - check_true(String(input[0]) === 'true', "String(input[0]) === 'true'") && - check_true(String(input[1]) === 'false', "String(input[1]) === 'false'")) { - for (var i = 0; i < input.length; ++i) { - if (!check_true(input[i] instanceof Boolean, 'input['+i+'] instanceof Boolean')) - return; - } - port.postMessage(input); - close(); - } - })(); - break; - case 'Object Boolean objects': - (function() { - if (check_true(input instanceof Object, 'input instanceof Object') && - check_true(!(input instanceof Array), '!(input instanceof Array)') && - check_true(String(input['true']) === 'true', "String(input['true']) === 'true'") && - check_true(String(input['false']) === 'false', "String(input['false']) === 'false'")) { - var i = 0; - for (var x in input) { - i++; - if (!check_true(input[x] instanceof Boolean, 'input['+x+'] instanceof Boolean')) - return; - } - if (check_true(i === 2, 'i === 2')) { - port.postMessage(input); - close(); - } - } - })(); - break; - case 'String empty string': - if (check_true(input instanceof String, "input instanceof String") && - check_true(String(input) === '', "String(input) === ''")) { - port.postMessage(input); - close(); - } - break; - case 'String lone high surrogate': - if (check_true(input instanceof String, "input instanceof String") && - check_true(String(input) === '\uD800', "String(input) === '\\uD800'")) { - port.postMessage(input); - close(); - } - break; - case 'String lone low surrogate': - if (check_true(input instanceof String, "input instanceof String") && - check_true(String(input) === '\uDC00', "String(input) === '\\uDC00'")) { - port.postMessage(input); - close(); - } - break; - case 'String NUL': - if (check_true(input instanceof String, "input instanceof String") && - check_true(String(input) === '\u0000', "String(input) === '\\u0000'")) { - port.postMessage(input); - close(); - } - break; - case 'String astral character': - if (check_true(input instanceof String, "input instanceof String") && - check_true(String(input) === '\uDBFF\uDFFD', "String(input) === '\\uDBFF\\uDFFD'")) { - port.postMessage(input); - close(); - } - break; - case 'Array String objects': - (function() { - if (check_true(input instanceof Array, 'input instanceof Array') && - check_true(input.length === 5, 'input.length === 5') && - check_true(String(input[0]) === '', "String(input[0]) === ''") && - check_true(String(input[1]) === '\uD800', "String(input[1]) === '\\uD800'") && - check_true(String(input[2]) === '\uDC00', "String(input[1]) === '\\uDC00'") && - check_true(String(input[3]) === '\u0000', "String(input[2]) === '\\u0000'") && - check_true(String(input[4]) === '\uDBFF\uDFFD', "String(input[3]) === '\\uDBFF\\uDFFD'")) { - for (var i = 0; i < input.length; ++i) { - if (!check_true(input[i] instanceof String, 'input['+i+'] instanceof String')) - return; - } - port.postMessage(input); - close(); - } - })(); - break; - case 'Object String objects': - (function() { - if (check_true(input instanceof Object, 'input instanceof Object') && - check_true(!(input instanceof Array), '!(input instanceof Array)') && - check_true(String(input['empty']) === '', "String(input['empty']) === ''") && - check_true(String(input['high surrogate']) === '\uD800', "String(input['high surrogate']) === '\\uD800'") && - check_true(String(input['low surrogate']) === '\uDC00', "String(input['low surrogate']) === '\\uDC00'") && - check_true(String(input['nul']) === '\u0000', "String(input['nul']) === '\\u0000'") && - check_true(String(input['astral']) === '\uDBFF\uDFFD', "String(input['astral']) === '\\uDBFF\\uDFFD'")) { - var i = 0; - for (var x in input) { - i++; - if (!check_true(input[x] instanceof String, 'input['+x+'] instanceof Boolean')) - return; - } - if (check_true(i === 5, 'i === 5')) { - port.postMessage(input); - close(); - } - } - })(); - break; - case 'Number 0.2': - if (check_true(input instanceof Number, "input instanceof Number") && - check_true(Number(input) === 0.2, "Number(input) === 0.2")) { - port.postMessage(input); - close(); - } - break; - case 'Number 0': - if (check_true(input instanceof Number, "input instanceof Number") && - check_true(1/Number(input) === Infinity, "1/Number(input) === Infinity")) { - port.postMessage(input); - close(); - } - break; - case 'Number -0': - if (check_true(input instanceof Number, "input instanceof Number") && - check_true(1/Number(input) === -Infinity, "1/Number(input) === -Infinity")) { - port.postMessage(input); - close(); - } - break; - case 'Number NaN': - if (check_true(input instanceof Number, "input instanceof Number") && - check_true(Number(input) !== Number(input), "Number(input) !== Number(input)")) { - port.postMessage(input); - close(); - } - break; - case 'Number Infinity': - if (check_true(input instanceof Number, "input instanceof Number") && - check_true(Number(input) === Infinity, "Number(input) === Infinity")) { - port.postMessage(input); - close(); - } - break; - case 'Number -Infinity': - if (check_true(input instanceof Number, "input instanceof Number") && - check_true(Number(input) === -Infinity, "Number(input) === -Infinity")) { - port.postMessage(input); - close(); - } - break; - case 'Number 9007199254740992': - if (check_true(input instanceof Number) && - check_true(Number(input) === 9007199254740992, "Number(input) === 9007199254740992")) { - port.postMessage(input); - close(); - } - break; - case 'Number -9007199254740992': - if (check_true(input instanceof Number, "input instanceof Number") && - check_true(Number(input) === -9007199254740992, "Number(input) === -9007199254740992")) { - port.postMessage(input); - close(); - } - break; - case 'Number 9007199254740994': - if (check_true(input instanceof Number, "input instanceof Number") && - check_true(Number(input) === 9007199254740994, "Number(input) === 9007199254740994")) { - port.postMessage(input); - close(); - } - break; - case 'Number -9007199254740994': - if (check_true(input instanceof Number, "input instanceof Number") && - check_true(Number(input) === -9007199254740994, "Number(input) === -9007199254740994")) { - port.postMessage(input); - close(); - } - break; - case 'Array Number objects': - (function() { - if (check_true(input instanceof Array, 'input instanceof Array') && - check_true(input.length === 10, 'input.length === 10') && - check_true(Number(input[0]) === 0.2, "Number(input[0]) === 0.2") && - check_true(1/Number(input[1]) === Infinity, "1/Number(input[1]) === Infinity") && - check_true(1/Number(input[2]) === -Infinity, "1/Number(input[2]) === -Infinity") && - check_true(Number(input[3]) !== Number(input[3]), "Number(input[3]) !== Number(input[3])") && - check_true(Number(input[4]) === Infinity, "Number(input[4]) === Infinity") && - check_true(Number(input[5]) === -Infinity, "Number(input[5]) === -Infinity") && - check_true(Number(input[6]) === 9007199254740992, "Number(input[6]) === 9007199254740992") && - check_true(Number(input[7]) === -9007199254740992, "Number(input[7]) === -9007199254740992") && - check_true(Number(input[8]) === 9007199254740994, "Number(input[8]) === 9007199254740994") && - check_true(Number(input[9]) === -9007199254740994, "Number(input[9]) === -9007199254740994")) { - for (var i = 0; i < input.length; ++i) { - if (!check_true(input[i] instanceof Number, 'input['+i+'] instanceof Number')) - return; - } - port.postMessage(input); - close(); - } - })(); - break; - case 'Object Number objects': - (function() { - if (check_true(input instanceof Object, 'input instanceof Object') && - check_true(!(input instanceof Array), '!(input instanceof Array)') && - check_true(Number(input['0.2']) === 0.2, "Number(input['0.2']) === 0.2") && - check_true(1/Number(input['0']) === Infinity, "1/Number(input['0']) === Infinity") && - check_true(1/Number(input['-0']) === -Infinity, "1/Number(input['-0']) === -Infinity") && - check_true(Number(input['NaN']) !== Number(input['NaN']), "Number(input['NaN']) !== Number(input['NaN'])") && - check_true(Number(input['Infinity']) === Infinity, "Number(input['Infinity']) === Infinity") && - check_true(Number(input['-Infinity']) === -Infinity, "Number(input['-Infinity']) === -Infinity") && - check_true(Number(input['9007199254740992']) === 9007199254740992, "Number(input['9007199254740992']) === 9007199254740992") && - check_true(Number(input['-9007199254740992']) === -9007199254740992, "Number(input['-9007199254740992']) === -9007199254740992") && - check_true(Number(input['9007199254740994']) === 9007199254740994, "Number(input['9007199254740994']) === 9007199254740994") && - check_true(Number(input['-9007199254740994']) === -9007199254740994, "Number(input['-9007199254740994']) === -9007199254740994")) { - var i = 0; - for (var x in input) { - i++; - if (!check_true(input[x] instanceof Number, 'input['+x+'] instanceof Number')) - return; - } - if (check_true(i === 10, 'i === 10')) { - port.postMessage(input); - close(); - } - } - })(); - break; - case 'Date 0': - if (check_true(input instanceof Date, "input instanceof Date") && - check_true(1/Number(input) === 1/Number(new Date(0)), "1/Number(input) === 1/Number(new Date(0))")) { - port.postMessage(input); - close(); - } - break; - case 'Date -0': - if (check_true(input instanceof Date, "input instanceof Date") && - check_true(1/Number(input) === 1/Number(new Date(-0)), "1/Number(input) === 1/Number(new Date(-0))")) { - port.postMessage(input); - close(); - } - break; - case 'Date -8.64e15': - if (check_true(input instanceof Date, "input instanceof Date") && - check_true(Number(input) === -8.64e15, "Number(input) === -8.64e15")) { - port.postMessage(input); - close(); - } - break; - case 'Date 8.64e15': - if (check_true(input instanceof Date, "input instanceof Date") && - check_true(Number(input) === 8.64e15, "Number(input) === 8.64e15")) { - port.postMessage(input); - close(); - } - break; - case 'Array Date objects': - (function() { - if (check_true(input instanceof Array, 'input instanceof Array') && - check_true(input.length === 4, 'input.length === 4') && - check_true(1/Number(input[0]) === 1/new Date(0), '1/Number(input[0]) === 1/new Date(0)') && - check_true(1/Number(input[1]) === 1/new Date(-0), '1/Number(input[1]) === 1/new Date(-0)') && - check_true(Number(input[2]) === -8.64e15, 'Number(input[2]) === -8.64e15') && - check_true(Number(input[3]) === 8.64e15, 'Number(input[3]) === 8.64e15')) { - for (var i = 0; i < input.length; ++i) { - if (!check_true(input[i] instanceof Date, 'input['+i+'] instanceof Date')) - return; - } - port.postMessage(input); - close(); - } - })(); - break; - case 'Object Date objects': - (function() { - if (check_true(input instanceof Object, 'input instanceof Object') && - check_true(!(input instanceof Array), '!(input instanceof Array)') && - check_true(1/Number(input['0']) === 1/new Date(0), "1/Number(input['0']) === 1/new Date(0)") && - check_true(1/Number(input['-0']) === 1/new Date(-0), "1/Number(input[1]) === 1/new Date(-0)") && - check_true(Number(input['-8.64e15']) === -8.64e15, "Number(input['-8.64e15']) === -8.64e15") && - check_true(Number(input['8.64e15']) === 8.64e15, "Number(input['8.64e15']) === 8.64e15")) { - var i = 0; - for (var x in input) { - i++; - if (!check_true(input[x] instanceof Date, 'input['+x+'] instanceof Date')) - return; - } - port.postMessage(input); - close(); - } - })(); - break; - case 'RegExp flags and lastIndex': - case 'RegExp empty': - case 'RegExp slash': - case 'RegExp new line': - if (check_RegExp(msg, input)) { - port.postMessage(input); - close(); - } - break; - case 'Array RegExp object, RegExp flags and lastIndex': - case 'Array RegExp object, RegExp empty': - case 'Array RegExp object, RegExp slash': - case 'Array RegExp object, RegExp new line': - if (check_true(input instanceof Array, 'input instanceof Array') && - check_true(input.length === 1, 'input.length === 1') && - check_RegExp(msg.substr('Array RegExp object, '.length), input[0])) { - port.postMessage(input); - close(); - } - break; - case 'Object RegExp object, RegExp flags and lastIndex': - case 'Object RegExp object, RegExp empty': - case 'Object RegExp object, RegExp slash': - case 'Object RegExp object, RegExp new line': - (function() { - if (check_true(input instanceof Object, 'input instanceof Object') && - check_true(!(input instanceof Array), '!(input instanceof Array)') && - check_RegExp(msg.substr('Object RegExp object, '.length), input['x'])) { - var i = 0; - for (var x in input) { - i++; - } - if (check_true(i === 1, 'i === 1')) { - port.postMessage(input); - close(); - } - } - })(); - break; - case 'Blob basic': - case 'Blob unpaired high surrogate (invalid utf-8)': - case 'Blob unpaired low surrogate (invalid utf-8)': - case 'Blob paired surrogates (invalid utf-8)': - case 'Blob empty': - case 'Blob NUL': - check_Blob(msg, input, port); - // no postMessage or close here, check_Blob takes care of that - break; - case 'Array Blob object, Blob basic': - case 'Array Blob object, Blob unpaired high surrogate (invalid utf-8)': - case 'Array Blob object, Blob unpaired low surrogate (invalid utf-8)': - case 'Array Blob object, Blob paired surrogates (invalid utf-8)': - case 'Array Blob object, Blob empty': - case 'Array Blob object, Blob NUL': - if (check_true(input instanceof Array, 'input instanceof Array') && - check_true(input.length === 1, 'input.length === 1')) { - check_Blob(msg.substr('Array Blob object, '.length), input[0], port, false, input); - // no postMessage or close here, check_Blob takes care of that - } - break; - case 'Object Blob object, Blob basic': - case 'Object Blob object, Blob unpaired high surrogate (invalid utf-8)': - case 'Object Blob object, Blob unpaired low surrogate (invalid utf-8)': - case 'Object Blob object, Blob paired surrogates (invalid utf-8)': - case 'Object Blob object, Blob empty': - case 'Object Blob object, Blob NUL': - (function() { - if (check_true(input instanceof Object, 'input instanceof Object') && - check_true(!(input instanceof Array), '!(input instanceof Array)')) { - var i = 0; - for (var x in input) { - i++; - } - if (check_true(i === 1, 'i === 1')) { - check_Blob(msg.substr('Object Blob object, '.length), input['x'], port, false, input); - // no postMessage or close here, check_Blob takes care of that - } - } - })(); - break; - case 'File basic': - check_Blob(msg, input, port, true); - // no postMessage or close here, check_Blob takes care of that - break; - case 'FileList empty': - if (check_FileList(msg, input)) { - port.postMessage(input); - close(); - } - break; - case 'Array FileList object, FileList empty': - if (check_true(input instanceof Array, 'input instanceof Array') && - check_true(input.length === 1, 'input.length === 1') && - check_FileList(msg.substr('Array FileList object, '.length), input[0])) { - port.postMessage(input); - close(); - } - break; - case 'Object FileList object, FileList empty': - (function() { - if (check_true(input instanceof Object, 'input instanceof Object') && - check_true(!(input instanceof Array), '!(input instanceof Array)') && - check_FileList(msg.substr('Array FileList object, '.length), input['x'])) { - var i = 0; - for (var x in input) { - i++; - } - if (check_true(i === 1, 'i === 1')) { - port.postMessage(input); - close(); - } - } - })(); - break; - case 'ImageData 1x1 transparent black': - if (check_ImageData(input, {width:1, height:1, data:[0,0,0,0]})) { - port.postMessage(input); - close(); - } - break; - case 'ImageData 1x1 non-transparent non-black': - if (check_ImageData(input, {width:1, height:1, data:[100, 101, 102, 103]})) { - port.postMessage(input); - close(); - } - break; - case 'Array ImageData object, ImageData 1x1 transparent black': - if (check_true(input instanceof Array, 'input instanceof Array') && - check_true(input.length === 1, 'input.length === 1') && - check_ImageData(input[0], {width:1, height:1, data:[0,0,0,0]})) { - port.postMessage(input); - close(); - } - break; - case 'Array ImageData object, ImageData 1x1 non-transparent non-black': - if (check_true(input instanceof Array, 'input instanceof Array') && - check_true(input.length === 1, 'input.length === 1') && - check_ImageData(input[0], {width:1, height:1, data:[100, 101, 102, 103]})) { - port.postMessage(input); - close(); - } - break; - case 'Object ImageData object, ImageData 1x1 transparent black': - (function(){ - if (check_true(input instanceof Object, 'input instanceof Object') && - check_true(!(input instanceof Array), '!(input instanceof Array)') && - check_ImageData(input['x'], {width:1, height:1, data:[0,0,0,0]})) { - var i = 0; - for (var x in input) { - i++; - } - if (check_true(i === 1, 'i === 1')) { - port.postMessage(input); - close(); - } - } - })(); - break; - case 'Object ImageData object, ImageData 1x1 non-transparent non-black': - (function() { - if (check_true(input instanceof Object, 'input instanceof Object') && - check_true(!(input instanceof Array), '!(input instanceof Array)') && - check_ImageData(input['x'], {width:1, height:1, data:[100, 101, 102, 103]})) { - var i = 0; - for (var x in input) { - i++; - } - if (check_true(i === 1, 'i === 1')) { - port.postMessage(input); - close(); - } - } - })(); - break; - case 'ImageBitmap 1x1 transparent black': - if (check_ImageBitmap(input, {width:1, height:1, data:[0, 0, 0, 0]})) { - port.postMessage(input); - close(); - } - break; - case 'ImageBitmap 1x1 non-transparent non-black': - if (check_ImageBitmap(input, {width:1, height:1, data:[100, 101, 102, 103]})) { - port.postMessage(input); - close(); - } - break; - case 'Array ImageBitmap object, ImageBitmap 1x1 transparent black': - if (check_true(input instanceof Array, 'input instanceof Array') && - check_true(input.length === 1, 'input.length === 1') && - check_ImageBitmap(input[0], {width:1, height:1, data:[0, 0, 0, 0]})) { - port.postMessage(input); - close(); - } - break; - case 'Array ImageBitmap object, ImageBitmap 1x1 non-transparent non-black': - if (check_true(input instanceof Array, 'input instanceof Array') && - check_true(input.length === 1, 'input.length === 1') && - check_ImageBitmap(input[0], {width:1, height:1, data:[100, 101, 102, 103]})) { - port.postMessage(input); - close(); - } - break; - case 'Object ImageBitmap object, ImageBitmap 1x1 transparent black': - (function() { - if (check_true(input instanceof Object, 'input instanceof Object') && - check_true(!(input instanceof Array), '!(input instanceof Array)') && - check_ImageBitmap(input['x'], {width:1, height:1, data:[0, 0, 0, 0]})) { - var i = 0; - for (var x in input) { - i++; - } - if (check_true(i === 1, 'i === 1')) { - port.postMessage(input); - close(); - } - } - })(); - break; - case 'Object ImageBitmap object, ImageBitmap 1x1 non-transparent non-black': - (function() { - if (check_true(input instanceof Object, 'input instanceof Object') && - check_true(!(input instanceof Array), '!(input instanceof Array)') && - check_ImageBitmap(input['x'], {width:1, height:1, data:[100, 101, 102, 103]})) { - var i = 0; - for (var x in input) { - i++; - } - if (check_true(i === 1, 'i === 1')) { - port.postMessage(input); - close(); - } - } - })(); - break; - case 'Array sparse': - (function() { - if (check_true(input instanceof Array, 'input instanceof Array') && - check_true(input.length === 10, 'input.length === 10')) { - for (var x in input) { - check_true(false, 'unexpected enumerable property '+x); - return; - } - port.postMessage(input); - close(); - } - })(); - break; - case 'Array with non-index property': - if (check_true(input instanceof Array, 'input instanceof Array') && - check_true(input.length === 0, 'input.length === 0') && - check_true(input.foo === 'bar', "input.foo === 'bar'")) { - port.postMessage(input); - close(); - } - break; - case 'Object with index property and length': - if (check_true(input instanceof Object, 'input instanceof Object') && - check_true(!(input instanceof Array), '!(input instanceof Array)') && - check_true(input[0] === 'foo', "input[0] === 'foo'") && - check_true(input.length === 1, 'input.length === 1')) { - port.postMessage(input); - close(); - } - break; - case 'Array with circular reference': - if (check_true(input instanceof Array, 'input instanceof Array') && - check_true(input.length === 1, 'input.length === 1') && - check_true(input[0] === input, "input[0] === input")) { - port.postMessage(input); - close(); - } - break; - case 'Object with circular reference': - if (check_true(input instanceof Object, 'input instanceof Object') && - check_true(!(input instanceof Array), '!(input instanceof Array)') && - check_true(input['x'] === input, "input['x'] === input")) { - port.postMessage(input); - close(); - } - break; - case 'Array with identical property values': - if (check_true(input instanceof Array, 'input instanceof Array') && - check_true(input.length === 2, 'input.length === 2') && - check_true(input[0] === input[1], "input[0] === input[1]")) { - port.postMessage(input); - close(); - } - break; - case 'Object with identical property values': - if (check_true(input instanceof Object, 'input instanceof Object') && - check_true(!(input instanceof Array), '!(input instanceof Array)') && - check_true(input['x'] === input['y'], "input['x'] === input['y']")) { - port.postMessage(input); - close(); - } - break; - case 'Object with property on prototype': - case 'Object with non-enumerable property': - if (check_true(input instanceof Object, 'input instanceof Object') && - check_true(!(input instanceof Array), '!(input instanceof Array)') && - check_true(!('foo' in input), "!('foo' in input)")) { - input = {}; - Object.defineProperty(input, 'foo', {value:'bar', enumerable:false, writable:true, configurable:true}); - port.postMessage(input); - close(); - } - break; - case 'Object with non-writable property': - if (check_true(input instanceof Object, 'input instanceof Object') && - check_true(!(input instanceof Array), '!(input instanceof Array)') && - check_true(input.foo === 'bar', "input.foo === bar")) { - input.foo += ' baz'; - if (check_true(input.foo === 'bar baz', "input.foo === 'bar baz'")) { - input = {}; - Object.defineProperty(input, 'foo', {value:'bar', enumerable:true, writable:false, configurable:true}); - port.postMessage(input); - close(); - } - } - break; - case 'Object with non-configurable property': - if (check_true(input instanceof Object, 'input instanceof Object') && - check_true(!(input instanceof Array), '!(input instanceof Array)') && - check_true(input.foo === 'bar', "input.foo === bar")) { - delete input.foo; - if (check_true(!('foo' in input), "!('foo' in input)")) { - input = {}; - Object.defineProperty(input, 'foo', {value:'bar', enumerable:true, writable:true, configurable:false}); - port.postMessage(input); - close(); - } - } - break; - - default: - port.postMessage('FAIL: unknown test'); - close(); - } - if (log.length > 0) { - port.postMessage('FAIL '+log); - close(); - } - } catch (ex) { - port.postMessage('FAIL '+ex); - close(); - } -}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/001.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/001.html deleted file mode 100644 index e26e21c..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/001.html +++ /dev/null
@@ -1,35 +0,0 @@ -<!-- -var xhr = new XMLHttpRequest(); -var log = ''; -xhr.onreadystatechange = function(e) { - if (this.readyState == 4) { - if (this.responseXML != null) - log += 'responseXML was not null. '; - if (this.responseText != '<x>foo</x>') - log += 'responseText was ' + this.responseText + ', expected <x>foo</x>. '; - postMessage(log); - } -} -xhr.open('GET', '001-1.xml', true); -xhr.send(); -/* ---> -<!doctype html> -<title>async XMLHttpRequest in dedicated worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -var t = async_test(); -function runtest() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data, ''); - this.done(); - }); -} -</script> -<iframe src=001-1.xml onload="t.step(runtest);"></iframe> -<!-- -*/ -//--> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/002.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/002.html deleted file mode 100644 index 0d3386e..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/002.html +++ /dev/null
@@ -1,32 +0,0 @@ -<!-- -var xhr = new XMLHttpRequest(); -var log = ''; -xhr.open('GET', '001-1.xml', false); -xhr.send(); -if (xhr.responseXML != null) - log += 'responseXML was not null. '; -if (xhr.responseText != '<x>foo</x>') - log += 'responseText was ' + this.responseText + ', expected <x>foo</x>. '; -postMessage(log); - -/* ---> -<!doctype html> -<title>sync XMLHttpRequest in dedicated worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -var t = async_test(); -function runtest() { - var worker = new Worker('#'); - worker.onmessage = this.step_func(function(e) { - assert_equals(e.data, ''); - this.done(); - }); -} -</script> -<iframe src=001-1.xml onload="t.step(runtest);"></iframe> -<!-- -*/ -//--> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/003.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/003.html deleted file mode 100644 index 70edaf4..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/003.html +++ /dev/null
@@ -1,41 +0,0 @@ -<!-- -onconnect = function(e) { - var xhr = new XMLHttpRequest(); - var log = ''; - var port = e.ports[0]; - var postMessage = port.postMessage; - xhr.onreadystatechange = function(e) { - if (this.readyState == 4) { - if (this.responseXML != null) - log += 'responseXML was not null. '; - if (this.responseText && this.responseText != '<x>foo</x>') - log += 'responseText was ' + this.responseText + ', expected <x>foo</x>. '; - postMessage.call(port, log); - } - } - xhr.open('GET', '001-1.xml', true); - xhr.send(); -} - -/* ---> -<!doctype html> -<title>async XMLHttpRequest in shared worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -var t = async_test(); -function runtest() { - var worker = new SharedWorker('#', ''); - worker.port.onmessage = this.step_func(function(e) { - assert_equals(e.data, ''); - this.done(); - }); -} -</script> -<iframe src=001-1.xml onload="t.step(runtest);"></iframe> -<!-- -*/ -//--> -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/004.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/004.html deleted file mode 100644 index ec5893a..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/004.html +++ /dev/null
@@ -1,36 +0,0 @@ -<!-- -onconnect = function(e) { - var xhr = new XMLHttpRequest(); - var log = ''; - xhr.open('GET', '001-1.xml', false); - xhr.send(); - if (xhr.responseXML != null) - log += 'responseXML was not null. '; - if (xhr.responseText != '<x>foo</x>') - log += 'responseText was ' + xhr.responseText + ', expected <x>foo</x>. '; - e.ports[0].postMessage(log); -} - -/* ---> -<!doctype html> -<title>sync XMLHttpRequest in shared worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -var t = async_test(); -function runtest() { - var worker = new SharedWorker('#', ''); - worker.port.onmessage = this.step_func(function(e) { - assert_equals(e.data, ''); - this.done(); - }); -} -</script> -<iframe src=001-1.xml onload="t.step(runtest);"></iframe> -<!-- -*/ -//--> - -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/005.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/005.html deleted file mode 100644 index 84abdb0..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/005.html +++ /dev/null
@@ -1,21 +0,0 @@ -<!doctype html> -<title>base url, dedicated worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -var t = async_test(); -var i = 0; -function runtest() { - i++; - if (i != 2) - return; - var worker = new Worker('support/005-1.js'); - worker.onmessage = this.step_func(function(e) { - assert_true(e.data); - this.done(); - }); -} -</script> -<iframe src=001-1.xml onload="t.step(runtest);"></iframe> -<iframe src=support/001-1.xml onload="t.step(runtest);"></iframe>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/006.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/006.html deleted file mode 100644 index 7411b4ba..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/006.html +++ /dev/null
@@ -1,21 +0,0 @@ -<!doctype html> -<title>base url, shared worker</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<div id=log></div> -<script> -var t = async_test(); -var i = 0; -function runtest() { - i++; - if (i != 2) - return; - var worker = new SharedWorker('support/006-1.js',''); - worker.port.onmessage = this.step_func(function(e) { - assert_true(e.data); - this.done(); - }); -} -</script> -<iframe src=001-1.xml onload="t.step(runtest);"></iframe> -<iframe src=support/001-1.xml onload="t.step(runtest);"></iframe>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/support/001-1.xml b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/support/001-1.xml deleted file mode 100644 index ecea58a9..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/support/001-1.xml +++ /dev/null
@@ -1 +0,0 @@ -<x>bar</x> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/support/005-1.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/support/005-1.js deleted file mode 100644 index 45f6519..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/support/005-1.js +++ /dev/null
@@ -1,5 +0,0 @@ -var xhr = new XMLHttpRequest(); -xhr.open('GET', '001-1.xml', false); -xhr.send(); -var passed = xhr.responseText == '<x>bar</x>'; -postMessage(passed); \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/support/006-1.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/support/006-1.js deleted file mode 100644 index d446781..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/support/006-1.js +++ /dev/null
@@ -1,7 +0,0 @@ -onconnect = function(e) { - var xhr = new XMLHttpRequest(); - xhr.open('GET', '001-1.xml', false); - xhr.send(); - var passed = xhr.responseText == '<x>bar</x>'; - e.ports[0].postMessage(passed); -} \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ErrorEvent-error.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ErrorEvent-error.js deleted file mode 100644 index 930b54c..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ErrorEvent-error.js +++ /dev/null
@@ -1,9 +0,0 @@ -onerror = function(message, location, line, col, error) { - postMessage({ source: "onerror", value: error }); -} - -addEventListener("error", function(e) { - postMessage({ source: "event listener", value: e.error }); -}); - -throw "hello";
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ErrorEvent.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ErrorEvent.js deleted file mode 100644 index 22ea6d4..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ErrorEvent.js +++ /dev/null
@@ -1,10 +0,0 @@ -onmessage = function(evt) -{ - throw(new Error(evt.data)); -} - -onerror = function(message, location, line, col) -{ - postMessage( {"message": message, "filename": location, "lineno": line, "colno": col} ); - return false; // "not handled" so the error propagates up to the Worker object -}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ImportScripts.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ImportScripts.js deleted file mode 100644 index 7f2a2bc..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ImportScripts.js +++ /dev/null
@@ -1,9 +0,0 @@ -try -{ - importScripts("WorkerBasic.js"); -} -catch(ex) -{ - result = "Fail"; - postMessage(result); -}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ImportScriptsNetworkErr.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ImportScriptsNetworkErr.js deleted file mode 100644 index 8179c8b..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ImportScriptsNetworkErr.js +++ /dev/null
@@ -1,15 +0,0 @@ -var result = "Fail"; - -try -{ - importScripts("NonExistentFile.js"); -} -catch(ex) -{ - if (ex.code != null && ex.code == ex.NETWORK_ERR) - { - result = "Pass"; - } -} - -postMessage(result); \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/Timer.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/Timer.js deleted file mode 100644 index a86a224..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/Timer.js +++ /dev/null
@@ -1,50 +0,0 @@ -var count = 0; -var id; - -onmessage = function(evt) -{ - try - { - switch(evt.data) - { - case "TimeoutHandler": - count = 0; - id = setTimeout("TimeoutHandler()", 10); - postMessage('hello'); - break; - case "IntervalHandler": - count = 0; - id = setInterval("IntervalHandler()", 10); - postMessage('hello'); - break; - } - } - catch(ex) - { - postMessage("Fail"); - } -} - -function TimeoutHandler() -{ - count++; - postMessage("worker"); - - id = setTimeout("TimeoutHandler()", 10); - - if (count >= 2) - { - clearTimeout(id); - } -} - -function IntervalHandler() -{ - count++; - postMessage("worker"); - - if (count >= 2) - { - clearInterval(id); - } -}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerBasic.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerBasic.js deleted file mode 100644 index 6bb6d32..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerBasic.js +++ /dev/null
@@ -1,7 +0,0 @@ -var result = "Fail"; - -onmessage = function(evt) -{ - result = "Pass"; - postMessage(result); -} \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerClose.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerClose.js deleted file mode 100644 index 81f9999..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerClose.js +++ /dev/null
@@ -1,5 +0,0 @@ -onmessage = function(evt) -{ - postMessage(evt.data); - self.close(); -} \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerDataCloneErr.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerDataCloneErr.js deleted file mode 100644 index b7e8b0a..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerDataCloneErr.js +++ /dev/null
@@ -1,15 +0,0 @@ -var result = "Fail"; - -try -{ - postMessage(navigator); -} -catch(ex) -{ - if(ex.code != null && ex.code == ex.DATA_CLONE_ERR) - { - result = "Pass"; - } -} - -postMessage(result); \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerLocation.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerLocation.js deleted file mode 100644 index a57e2fc6..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerLocation.js +++ /dev/null
@@ -1,12 +0,0 @@ -var obj = new Object(); -obj.location = location.toString(); -obj.href = location.href; -obj.protocol = location.protocol; -obj.host = location.host; -obj.hostname = location.hostname; -obj.port = location.port; -obj.pathname = location.pathname; -obj.search = location.search; -obj.hash = location.hash; - -postMessage(obj);
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerNavigator.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerNavigator.js deleted file mode 100644 index 084e45b..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerNavigator.js +++ /dev/null
@@ -1,8 +0,0 @@ -var obj = new Object(); -obj.appName = navigator.appName; -obj.appVersion = navigator.appVersion; -obj.platform = navigator.platform; -obj.userAgent = navigator.userAgent; -obj.onLine = navigator.onLine; - -postMessage(obj);
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerTerminate.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerTerminate.js deleted file mode 100644 index 7c99e7e..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerTerminate.js +++ /dev/null
@@ -1,10 +0,0 @@ -onmessage = function(evt) -{ - for (var i=0; true; i++) - { - if (i%1000 == 0) - { - postMessage(i); - } - } -}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerText.txt b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerText.txt deleted file mode 100644 index e4eeb539..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerText.txt +++ /dev/null
@@ -1,2 +0,0 @@ -var result = "Pass"; -postMessage(result);
diff --git a/third_party/WebKit/LayoutTests/inspector/layers/layer-replay-scale-expected.txt b/third_party/WebKit/LayoutTests/inspector/layers/layer-replay-scale-expected.txt new file mode 100644 index 0000000..0277d78 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/layers/layer-replay-scale-expected.txt
@@ -0,0 +1,6 @@ +Tests that when layer snapshots are replayed with scaling applied the image dimensions are properly scaled. + + +Image dimensions at scale undefined: 180 x 180 +Image dimensions at scale 0.5: 90 x 90 +
diff --git a/third_party/WebKit/LayoutTests/inspector/layers/layer-replay-scale.html b/third_party/WebKit/LayoutTests/inspector/layers/layer-replay-scale.html new file mode 100644 index 0000000..f55a9853 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/layers/layer-replay-scale.html
@@ -0,0 +1,58 @@ +<html> +<head> +<script src="../../http/tests/inspector/inspector-test.js"></script> +<script src="../../http/tests/inspector/layers-test.js"></script> +<script> +function test() +{ + setTimeout(() => InspectorTest.completeTest(), 3000); + InspectorTest.requestLayers(onGotLayers); + + function onGotLayers() + { + var layer = InspectorTest.findLayerByNodeIdAttribute("a"); + layer.requestSnapshot(onSnapshotDone); + } + + function onSnapshotDone(snapshot) + { + testImageForSnapshot(snapshot, undefined).then(() => testImageForSnapshot(snapshot, 0.5)).then(() => InspectorTest.completeTest()); + } + + function testImageForSnapshot(snapshot, scale) + { + return new Promise(fulfill => { + InspectorTest.LayerTreeAgent.replaySnapshot(snapshot._id, undefined, undefined, scale, InspectorBackend.wrapClientCallback(fulfill, "LayerTreeAgent.replaySnapshot(): ")); + }).then(imageURL => new Promise(fulfill => { + var image = new Image(); + image.addEventListener("load", () => fulfill(image), false); + image.src = imageURL; + })).then(image => { + InspectorTest.addResult(`Image dimensions at scale ${scale}: ${image.naturalWidth} x ${image.naturalHeight}`); + }); + } +} +</script> +</head> +<body onload="runTest()"> +<p> +Tests that when layer snapshots are replayed with scaling applied the image dimensions are properly scaled. +</p> +<div id="a" style="background-color:blue; transform: translateZ(0px); overflow: hidden;"> + <script> +(function() +{ + var a = document.getElementById("a"); + var size = (180 / window.devicePixelRatio) + "px"; + a.style.width = size; + a.style.height = size; +})(); + </script> + <div style="width:50px; height:50px; background-color:red;"></div> + <img src="../tracing/resources/test.png"> + <svg> + <rect x="0" y="0" width="10" height="10" style="opacity:0.5"/> + </svg> + </div> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-requestmediakeysystemaccess.html b/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-requestmediakeysystemaccess.html index 3b053185..a9b85da 100644 --- a/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-requestmediakeysystemaccess.html +++ b/third_party/WebKit/LayoutTests/media/encrypted-media/encrypted-media-requestmediakeysystemaccess.html
@@ -312,6 +312,23 @@ expect_error('org.w3.clearkey', [{ videoCapabilities: [{contentType: 'video/webm; codecs=",vp8,"'}], }], 'NotSupportedError', 'Leading and trailing , in codecs'); + + // Verify 'temporary' sessionType. + expect_config('org.w3.clearkey', [{ + sessionTypes: [ 'temporary' ] + }], { + sessionTypes: [ 'temporary' ] + }, 'temporary sessionType'); + + // Clear Key doesn't support persistent sessions. + expect_error('org.w3.clearkey', [{ + sessionTypes: [ 'persistent-license' ] + }], 'NotSupportedError', 'persistent-license sessionType'); + + // Verify invalid sessionTypes. + expect_error('org.w3.clearkey', [{ + sessionTypes: [ 'foo' ] + }], 'NotSupportedError', 'invalid sessionType'); </script> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/svg/absolute-sized-document-no-scrollbars-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/svg/absolute-sized-document-no-scrollbars-expected.txt index b40526b..e4025737 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/svg/absolute-sized-document-no-scrollbars-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/svg/absolute-sized-document-no-scrollbars-expected.txt
@@ -15,11 +15,6 @@ "object": "LayoutSVGRoot svg", "rect": [0, 0, 576, 432], "reason": "style change" - }, - { - "object": "LayoutSVGRect rect", - "rect": [0, 0, 480, 360], - "reason": "style change" } ] }
diff --git a/third_party/WebKit/LayoutTests/payments/payment-request-interface.html b/third_party/WebKit/LayoutTests/payments/payment-request-interface.html index cda7c6a1..07d3abe 100644 --- a/third_party/WebKit/LayoutTests/payments/payment-request-interface.html +++ b/third_party/WebKit/LayoutTests/payments/payment-request-interface.html
@@ -156,6 +156,12 @@ }, 'Shipping option identifier should default to the last selected shipping option, if multiple are selected.'); test(function() { + var shippingOptions = [buildItem({'id': 'express', 'selected': false}), buildItem({'id': 'express', 'selected': true})]; + var request = new PaymentRequest([{'supportedMethods': ['foo']}], {'total': buildItem(), 'displayItems': [buildItem()], 'shippingOptions': shippingOptions}, {'requestShipping': true}); + assert_equals(null, request.shippingOption); +}, 'No shipping option selected for duplicate shipping option identifiers.'); + +test(function() { var request = new PaymentRequest([{'supportedMethods': ['foo']}], buildDetails(), {'requestShipping': false}); assert_equals(null, request.shippingType); }, 'Shipping type should be null if shipping is explicitly not requested.'); @@ -265,10 +271,6 @@ ['Duplicate supported payment method identifiers should throw TypeError.', null, function() { new PaymentRequest([{'supportedMethods': ['foo']}, {'supportedMethods': ['foo']}], buildDetails(), {}) }], - ['Duplicate shipping option identifiers should throw TypeError.', null, function() { - var shippingOptions = [buildItem({'id': 'express', 'selected': false}), buildItem({'id': 'express', 'selected': true})]; - new PaymentRequest([{'supportedMethods': ['foo']}], {'total': buildItem(), 'displayItems': [buildItem()], 'shippingOptions': shippingOptions}, {'requestShipping': true}) - }], ['Absence of total should throw TypeError.', null, function() { new PaymentRequest([{'supportedMethods': ['foo']}], {'displayItems': [buildItem()]}) }],
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/text-selection-text-05-t-expected.png b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/text-selection-text-05-t-expected.png index a3b4373..e804082ab 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/text-selection-text-05-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/svg/text-selection-text-05-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/small-fonts-in-html5-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/text/small-fonts-in-html5-expected.txt index 4669111..2b24ccb 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/small-fonts-in-html5-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/small-fonts-in-html5-expected.txt
@@ -8,7 +8,7 @@ text run at (0,0) width 472: "Small fonts in HTML5/inline SVG" LayoutBlockFlow (anonymous) at (0,58.44) size 784x507 LayoutSVGRoot {svg} at (8,79) size 502x503 - LayoutSVGContainer {g} at (159,268) size 94x20 [transform={m=((400.00,0.00)(0.00,400.00)) t=(0.00,0.00)}] + LayoutSVGContainer {g} at (159,267) size 94x21 [transform={m=((400.00,0.00)(0.00,400.00)) t=(0.00,0.00)}] LayoutSVGText {text} at (0,0) size 1x1 contains 1 chunk(s) LayoutSVGInlineText {#text} at (0,0) size 1x1 chunk 1 (middle anchor) text run 1 at (0.38,0.50) startOffset 0 endOffset 12 width 0.24: "Test passed."
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-01-b-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-01-b-expected.png index f455762..96b9e45 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-01-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-01-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-02-b-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-02-b-expected.png index 56192b9..64497d51 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-02-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-02-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-03-b-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-03-b-expected.png index 1efff6e..449a661 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-03-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-03-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-04-b-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-04-b-expected.png index 0e0c7c6..2018411 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-04-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-04-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-05-b-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-05-b-expected.png index 90cd0ad..94d48469 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-05-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-align-05-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-deco-01-b-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-deco-01-b-expected.png index 0c33204..1a770bfc5 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-deco-01-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-deco-01-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-fonts-01-t-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-fonts-01-t-expected.png index 2102e58..7a59d7a7 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-fonts-01-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-fonts-01-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-fonts-02-t-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-fonts-02-t-expected.png index 6602274..add3f213 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-fonts-02-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-fonts-02-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-intro-05-t-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-intro-05-t-expected.png index a706bdc..17a421d 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-intro-05-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-intro-05-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-path-01-b-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-path-01-b-expected.png index 02a386a60..6d66a1c 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-path-01-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-path-01-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-text-03-b-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-text-03-b-expected.png index f9bbad76..1c022ad 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-text-03-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-text-03-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-text-04-t-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-text-04-t-expected.png index 16844c3..6bda3d2 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-text-04-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-text-04-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-text-06-t-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-text-06-t-expected.png index cc0661b..369e0d6 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-text-06-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-text-06-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-text-07-t-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-text-07-t-expected.png index bb1d2ec..bf5d611 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-text-07-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-text-07-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-text-08-b-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-text-08-b-expected.png index 7d2bf7c6..bf6e34a 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-text-08-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-text-08-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-tselect-01-b-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-tselect-01-b-expected.png index 6c49582..ea40bdc2 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-tselect-01-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-tselect-01-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-tselect-02-f-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-tselect-02-f-expected.png index 468e2a2..8b17252 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-tselect-02-f-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-tselect-02-f-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-tspan-01-b-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-tspan-01-b-expected.png index 06adb82..2c041d15 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-tspan-01-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-tspan-01-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-ws-01-t-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-ws-01-t-expected.png index 2431f10..cfd3e4b 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-ws-01-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-ws-01-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-ws-02-t-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-ws-02-t-expected.png index 9efa4d8..1d02f42 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-ws-02-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/text/text-selection-ws-02-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/svg-css-transforms-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/svg-css-transforms-expected.png index e05cce8..5c5ffd9 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/svg-css-transforms-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/svg-css-transforms-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/svg-css-transforms-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/svg-css-transforms-expected.txt index 04c5e9eb..5af0729 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/svg-css-transforms-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/svg-css-transforms-expected.txt
@@ -23,11 +23,11 @@ layer at (28,85) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,66.81) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] LayoutSVGRoot {svg} at (29,108) size 196x175 - LayoutSVGContainer {g} at (29,109) size 196x173 [transform={m=((1.00,0.00)(0.00,1.00)) t=(75.00,25.00)}] - LayoutSVGRect {rect} at (103,110) size 62x62 [stroke={[type=SOLID] [color=#000000] [dash array={1.00, 1.00}]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] - LayoutSVGContainer {g} at (29,109) size 196x173 [transform={m=((2.00,0.00)(0.00,2.00)) t=(0.00,0.00)}] + LayoutSVGContainer {g} at (29,108) size 196x175 [transform={m=((1.00,0.00)(0.00,1.00)) t=(75.00,25.00)}] + LayoutSVGRect {rect} at (103,109) size 62x63 [stroke={[type=SOLID] [color=#000000] [dash array={1.00, 1.00}]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGContainer {g} at (29,108) size 196x175 [transform={m=((2.00,0.00)(0.00,2.00)) t=(0.00,0.00)}] LayoutSVGRect {rect} at (103,109) size 122x123 [stroke={[type=SOLID] [color=#000000] [dash array={1.00, 1.00}]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] - LayoutSVGRect {rect} at (29,109) size 162x173 [transform={m=((0.71,0.71)(-0.71,0.71)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGRect {rect} at (29,108) size 162x175 [transform={m=((0.71,0.71)(-0.71,0.71)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] LayoutText {#text} at (0,0) size 0x0 layer at (28,352) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,333.63) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] @@ -40,7 +40,7 @@ layer at (272,85) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,66.81) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] LayoutSVGRoot {svg} at (273,108) size 162x175 - LayoutSVGRect {rect} at (273,109) size 162x173 [transform={m=((1.41,1.41)(-1.41,1.41)) t=(75.00,25.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGRect {rect} at (273,108) size 162x175 [transform={m=((1.41,1.41)(-1.41,1.41)) t=(75.00,25.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] LayoutText {#text} at (0,0) size 0x0 layer at (272,352) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,333.63) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)]
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-clip-path-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-clip-path-expected.txt index d5e1b26..f474500 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-clip-path-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-clip-path-expected.txt
@@ -9,12 +9,12 @@ LayoutSVGRect {rect} at (16,16) size 105x105 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=50.00] [height=50.00] LayoutSVGResourceClipper {clipPath} [id="clip2"] [clipPathUnits=userSpaceOnUse] LayoutSVGRect {rect} at (16,16) size 105x105 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=50.00] [height=50.00] - LayoutSVGRect {rect} at (120,120) size 104x104 [fill={[type=SOLID] [color=#000000]}] [x=50.00] [y=50.00] [width=50.00] [height=50.00] + LayoutSVGRect {rect} at (119,119) size 105x105 [fill={[type=SOLID] [color=#000000]}] [x=50.00] [y=50.00] [width=50.00] [height=50.00] LayoutSVGResourceClipper {clipPath} [id="clip3"] [clipPathUnits=objectBoundingBox] - LayoutSVGRect {rect} at (16,16) size 2x2 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=0.50] [height=0.50] + LayoutSVGRect {rect} at (16,16) size 3x3 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=0.50] [height=0.50] LayoutSVGResourceClipper {clipPath} [id="clip4"] [clipPathUnits=objectBoundingBox] - LayoutSVGRect {rect} at (16,16) size 2x2 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=0.50] [height=0.50] - LayoutSVGRect {rect} at (17,17) size 2x2 [fill={[type=SOLID] [color=#000000]}] [x=0.50] [y=0.50] [width=0.50] [height=0.50] + LayoutSVGRect {rect} at (16,16) size 3x3 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=0.50] [height=0.50] + LayoutSVGRect {rect} at (17,17) size 3x3 [fill={[type=SOLID] [color=#000000]}] [x=0.50] [y=0.50] [width=0.50] [height=0.50] LayoutText {#text} at (0,0) size 0x0 LayoutText {#text} at (0,0) size 0x0 LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-foreignObject-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-foreignObject-expected.txt index 93d86ee..3354141 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-foreignObject-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-foreignObject-expected.txt
@@ -17,11 +17,11 @@ LayoutSVGRect {rect} at (0,0) size 361x289 [stroke={[type=SOLID] [color=#008000]}] [x=0.00] [y=0.00] [width=250.00] [height=200.00] LayoutSVGForeignObject {foreignObject} at (260,0) size 250x200 LayoutSVGRoot {svg} at (374,7) size 361x281 - LayoutSVGContainer {g} at (375,7) size 360x281 [transform={m=((3.00,0.26)(0.26,3.02)) t=(0.00,0.00)}] + LayoutSVGContainer {g} at (374,7) size 361x281 [transform={m=((3.00,0.26)(0.26,3.02)) t=(0.00,0.00)}] LayoutSVGText {text} at (0,1) size 81x19 contains 1 chunk(s) LayoutSVGInlineText {#text} at (0,0) size 81x19 chunk 1 text run 1 at (0.00,16.00) startOffset 0 endOffset 14 width 80.06: "This is a text" - LayoutSVGContainer {a} at (382,90) size 286x105 + LayoutSVGContainer {a} at (381,89) size 288x106 LayoutSVGText {text} at (0,20) size 65x19 contains 1 chunk(s) LayoutSVGInlineText {#text} at (0,0) size 65x19 chunk 1 text run 1 at (0.00,35.00) startOffset 0 endOffset 11 width 64.51: "and a link."
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-float-border-padding-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-float-border-padding-expected.txt index c9917b5..c5bf418 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-float-border-padding-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-float-border-padding-expected.txt
@@ -12,7 +12,7 @@ LayoutText {#text} at (0,0) size 524x26 text run at (0,0) width 524: "There should be a red, white and blue pattern below this" LayoutSVGRoot (floating) {svg} at (25,152) size 202x202 - LayoutSVGRect {rect} at (54,181) size 145x145 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00] + LayoutSVGRect {rect} at (53,180) size 146x146 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00] LayoutBlockFlow {p} at (0,356.63) size 761.97x27 LayoutText {#text} at (0,0) size 523x26 text run at (0,0) width 523: "There should be a red, white and blue pattern above this"
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/svg-vs-css-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/transforms/svg-vs-css-expected.txt index 146d49f..7a6847e 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/transforms/svg-vs-css-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/svg-vs-css-expected.txt
@@ -32,11 +32,11 @@ layer at (28,85) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,66.81) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] LayoutSVGRoot {svg} at (29,108) size 196x175 - LayoutSVGContainer {g} at (29,109) size 196x173 [transform={m=((1.00,0.00)(0.00,1.00)) t=(75.00,25.00)}] - LayoutSVGRect {rect} at (103,110) size 62x62 [stroke={[type=SOLID] [color=#000000] [dash array={1.00, 1.00}]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] - LayoutSVGContainer {g} at (29,109) size 196x173 [transform={m=((2.00,0.00)(0.00,2.00)) t=(0.00,0.00)}] + LayoutSVGContainer {g} at (29,108) size 196x175 [transform={m=((1.00,0.00)(0.00,1.00)) t=(75.00,25.00)}] + LayoutSVGRect {rect} at (103,109) size 62x63 [stroke={[type=SOLID] [color=#000000] [dash array={1.00, 1.00}]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGContainer {g} at (29,108) size 196x175 [transform={m=((2.00,0.00)(0.00,2.00)) t=(0.00,0.00)}] LayoutSVGRect {rect} at (103,109) size 122x123 [stroke={[type=SOLID] [color=#000000] [dash array={1.00, 1.00}]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] - LayoutSVGRect {rect} at (29,109) size 162x173 [transform={m=((0.71,0.71)(-0.71,0.71)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGRect {rect} at (29,108) size 162x175 [transform={m=((0.71,0.71)(-0.71,0.71)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] LayoutText {#text} at (0,0) size 0x0 layer at (28,352) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,333.63) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] @@ -49,7 +49,7 @@ layer at (272,85) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,66.81) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] LayoutSVGRoot {svg} at (273,108) size 162x175 - LayoutSVGRect {rect} at (273,109) size 162x173 [transform={m=((1.41,1.41)(-1.41,1.41)) t=(75.00,25.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGRect {rect} at (273,108) size 162x175 [transform={m=((1.41,1.41)(-1.41,1.41)) t=(75.00,25.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] LayoutText {#text} at (0,0) size 0x0 layer at (272,352) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,333.63) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] @@ -58,7 +58,7 @@ layer at (516,85) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,66.81) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] LayoutSVGRoot {svg} at (517,108) size 162x175 - LayoutSVGRect {rect} at (517,109) size 162x173 [transform={m=((1.41,1.41)(-1.41,1.41)) t=(75.00,25.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGRect {rect} at (517,108) size 162x175 [transform={m=((1.41,1.41)(-1.41,1.41)) t=(75.00,25.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] LayoutText {#text} at (0,0) size 0x0 layer at (516,352) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,333.63) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)]
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/svg/text/text-selection-fonts-01-t-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/svg/text/text-selection-fonts-01-t-expected.png index ae48c74..fdfd69ed 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/svg/text/text-selection-fonts-01-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/svg/text/text-selection-fonts-01-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/block/basic/fieldset-stretch-to-legend-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/block/basic/fieldset-stretch-to-legend-expected.png deleted file mode 100644 index e458bbd..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/block/basic/fieldset-stretch-to-legend-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/text/text-selection-fonts-01-t-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/text/text-selection-fonts-01-t-expected.png index 0db0079..60bc23e1 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/text/text-selection-fonts-01-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/text/text-selection-fonts-01-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/text/text-selection-intro-05-t-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/text/text-selection-intro-05-t-expected.png index d3d281f..f3e4b23 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/text/text-selection-intro-05-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/svg/text/text-selection-intro-05-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/block/basic/fieldset-stretch-to-legend-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/block/basic/fieldset-stretch-to-legend-expected.png deleted file mode 100644 index 10fa307..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/block/basic/fieldset-stretch-to-legend-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/text-selection-text-05-t-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/text-selection-text-05-t-expected.png index 11549d1..c01de00e 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/text-selection-text-05-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/svg/text-selection-text-05-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/embedding-external-svgs-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/embedding-external-svgs-expected.txt index e8615eb1..f8da330 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/embedding-external-svgs-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/embedding-external-svgs-expected.txt
@@ -22,17 +22,17 @@ LayoutSVGRoot {svg:svg} at (91,278) size 31x30 LayoutSVGContainer {svg:g} at (91,278) size 31x30 LayoutSVGPath {svg:polygon} at (104,278) size 5x8 [fill={[type=SOLID] [color=#000000] [opacity=0.04]}] [points="22 0 28 0 27 12 23 12"] - LayoutSVGPath {svg:polygon} at (108,279) size 8x9 [transform={m=((0.87,0.50)(-0.50,0.87)) t=(15.85,-9.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.08]}] [points="22 0 28 0 27 12 23 12"] - LayoutSVGPath {svg:polygon} at (112,283) size 9x8 [transform={m=((0.50,0.87)(-0.87,0.50)) t=(34.15,-9.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.12]}] [points="22 0 28 0 27 12 23 12"] - LayoutSVGPath {svg:polygon} at (114,291) size 8x4 [transform={m=((0.00,1.00)(-1.00,0.00)) t=(50.00,0.00)}] [fill={[type=SOLID] [color=#000000] [opacity=0.16]}] [points="22 0 28 0 27 12 23 12"] - LayoutSVGPath {svg:polygon} at (112,295) size 9x8 [transform={m=((-0.50,0.87)(-0.87,-0.50)) t=(59.15,15.85)}] [fill={[type=SOLID] [color=#000000] [opacity=0.20]}] [points="22 0 28 0 27 12 23 12"] - LayoutSVGPath {svg:polygon} at (108,298) size 8x9 [transform={m=((-0.87,0.50)(-0.50,-0.87)) t=(59.15,34.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.24]}] [points="22 0 28 0 27 12 23 12"] + LayoutSVGPath {svg:polygon} at (108,279) size 9x9 [transform={m=((0.87,0.50)(-0.50,0.87)) t=(15.85,-9.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.08]}] [points="22 0 28 0 27 12 23 12"] + LayoutSVGPath {svg:polygon} at (111,283) size 10x8 [transform={m=((0.50,0.87)(-0.87,0.50)) t=(34.15,-9.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.12]}] [points="22 0 28 0 27 12 23 12"] + LayoutSVGPath {svg:polygon} at (113,291) size 9x4 [transform={m=((0.00,1.00)(-1.00,0.00)) t=(50.00,0.00)}] [fill={[type=SOLID] [color=#000000] [opacity=0.16]}] [points="22 0 28 0 27 12 23 12"] + LayoutSVGPath {svg:polygon} at (111,295) size 10x8 [transform={m=((-0.50,0.87)(-0.87,-0.50)) t=(59.15,15.85)}] [fill={[type=SOLID] [color=#000000] [opacity=0.20]}] [points="22 0 28 0 27 12 23 12"] + LayoutSVGPath {svg:polygon} at (108,298) size 9x9 [transform={m=((-0.87,0.50)(-0.50,-0.87)) t=(59.15,34.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.24]}] [points="22 0 28 0 27 12 23 12"] LayoutSVGPath {svg:polygon} at (104,300) size 5x8 [transform={m=((-1.00,0.00)(-0.00,-1.00)) t=(50.00,50.00)}] [fill={[type=SOLID] [color=#000000] [opacity=0.29]}] [points="22 0 28 0 27 12 23 12"] - LayoutSVGPath {svg:polygon} at (97,298) size 7x9 [transform={m=((-0.87,-0.50)(0.50,-0.87)) t=(34.15,59.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.33]}] [points="22 0 28 0 27 12 23 12"] - LayoutSVGPath {svg:polygon} at (92,295) size 9x8 [transform={m=((-0.50,-0.87)(0.87,-0.50)) t=(15.85,59.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.37]}] [points="22 0 28 0 27 12 23 12"] - LayoutSVGPath {svg:polygon} at (91,291) size 8x4 [transform={m=((-0.00,-1.00)(1.00,-0.00)) t=(0.00,50.00)}] [fill={[type=SOLID] [color=#000000] [opacity=0.41]}] [points="22 0 28 0 27 12 23 12"] - LayoutSVGPath {svg:polygon} at (92,283) size 9x8 [transform={m=((0.50,-0.87)(0.87,0.50)) t=(-9.15,34.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.45]}] [points="22 0 28 0 27 12 23 12"] - LayoutSVGPath {svg:polygon} at (97,279) size 7x9 [transform={m=((0.87,-0.50)(0.50,0.87)) t=(-9.15,15.85)}] [fill={[type=SOLID] [color=#000000] [opacity=0.50]}] [points="22 0 28 0 27 12 23 12"] + LayoutSVGPath {svg:polygon} at (96,298) size 9x9 [transform={m=((-0.87,-0.50)(0.50,-0.87)) t=(34.15,59.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.33]}] [points="22 0 28 0 27 12 23 12"] + LayoutSVGPath {svg:polygon} at (92,295) size 10x8 [transform={m=((-0.50,-0.87)(0.87,-0.50)) t=(15.85,59.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.37]}] [points="22 0 28 0 27 12 23 12"] + LayoutSVGPath {svg:polygon} at (91,291) size 9x4 [transform={m=((-0.00,-1.00)(1.00,-0.00)) t=(0.00,50.00)}] [fill={[type=SOLID] [color=#000000] [opacity=0.41]}] [points="22 0 28 0 27 12 23 12"] + LayoutSVGPath {svg:polygon} at (92,283) size 10x8 [transform={m=((0.50,-0.87)(0.87,0.50)) t=(-9.15,34.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.45]}] [points="22 0 28 0 27 12 23 12"] + LayoutSVGPath {svg:polygon} at (96,279) size 9x9 [transform={m=((0.87,-0.50)(0.50,0.87)) t=(-9.15,15.85)}] [fill={[type=SOLID] [color=#000000] [opacity=0.50]}] [points="22 0 28 0 27 12 23 12"] LayoutText {#text} at (0,0) size 0x0 layer at (290,16) size 40x40 LayoutEmbeddedObject {embed} at (239.69,0) size 40x40
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/bbox-with-glyph-overflow-zoomed-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/text/bbox-with-glyph-overflow-zoomed-expected.txt index 3aabd704..0dcca20 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/bbox-with-glyph-overflow-zoomed-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/bbox-with-glyph-overflow-zoomed-expected.txt
@@ -46,8 +46,8 @@ LayoutSVGText {text} at (19,61) size 27x20 contains 1 chunk(s) LayoutSVGInlineText {#text} at (0,0) size 26x19 chunk 1 text run 1 at (20.00,75.00) startOffset 0 endOffset 5 width 23.16: "'faQ'" - LayoutSVGRect {rect} at (46,63) size 153x27 [stroke={[type=SOLID] [color=#008000]}] [fill={[type=SOLID] [color=#00000000]}] [x=18.20] [y=9.45] [width=83.52] [height=13.33] - LayoutSVGRect {rect} at (46,98) size 120x52 [stroke={[type=SOLID] [color=#008000]}] [fill={[type=SOLID] [color=#00000000]}] [x=18.20] [y=28.89] [width=65.27] [height=27.22] - LayoutSVGRect {rect} at (49,157) size 48x37 [stroke={[type=SOLID] [color=#008000]}] [fill={[type=SOLID] [color=#00000000]}] [x=19.80] [y=61.67] [width=25.38] [height=18.88] + LayoutSVGRect {rect} at (45,63) size 154x27 [stroke={[type=SOLID] [color=#008000]}] [fill={[type=SOLID] [color=#00000000]}] [x=18.20] [y=9.45] [width=83.52] [height=13.33] + LayoutSVGRect {rect} at (45,98) size 122x52 [stroke={[type=SOLID] [color=#008000]}] [fill={[type=SOLID] [color=#00000000]}] [x=18.20] [y=28.89] [width=65.27] [height=27.22] + LayoutSVGRect {rect} at (48,157) size 50x37 [stroke={[type=SOLID] [color=#008000]}] [fill={[type=SOLID] [color=#00000000]}] [x=19.80] [y=61.67] [width=25.38] [height=18.88] LayoutText {#text} at (0,0) size 0x0 LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/small-fonts-in-html5-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/text/small-fonts-in-html5-expected.txt index 1c8a3f80..7f78e28 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/small-fonts-in-html5-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/small-fonts-in-html5-expected.txt
@@ -8,7 +8,7 @@ text run at (0,0) width 470: "Small fonts in HTML5/inline SVG" LayoutBlockFlow (anonymous) at (0,58.44) size 784x506 LayoutSVGRoot {svg} at (8,79) size 502x503 - LayoutSVGContainer {g} at (159,268) size 94x20 [transform={m=((400.00,0.00)(0.00,400.00)) t=(0.00,0.00)}] + LayoutSVGContainer {g} at (159,267) size 94x21 [transform={m=((400.00,0.00)(0.00,400.00)) t=(0.00,0.00)}] LayoutSVGText {text} at (0,0) size 1x1 contains 1 chunk(s) LayoutSVGInlineText {#text} at (0,0) size 1x1 chunk 1 (middle anchor) text run 1 at (0.38,0.50) startOffset 0 endOffset 12 width 0.24: "Test passed."
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-align-01-b-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-align-01-b-expected.png index 293e83d..152dd2c 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-align-01-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-align-01-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-align-02-b-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-align-02-b-expected.png index 4b511830..dca52b9 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-align-02-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-align-02-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-align-05-b-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-align-05-b-expected.png index a568361..2f23730 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-align-05-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-align-05-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-deco-01-b-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-deco-01-b-expected.png index c9e5b795..f63da43 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-deco-01-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-deco-01-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-fonts-01-t-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-fonts-01-t-expected.png index 9a6c98ea..6590a6b 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-fonts-01-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-fonts-01-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-fonts-02-t-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-fonts-02-t-expected.png index d0b04db..a529a969 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-fonts-02-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-fonts-02-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-intro-05-t-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-intro-05-t-expected.png index f6e8e72b..ba47e87 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-intro-05-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-intro-05-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-text-03-b-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-text-03-b-expected.png index b1752d8..2ede290 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-text-03-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-text-03-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-text-04-t-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-text-04-t-expected.png index 28726cf..28cd871 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-text-04-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-text-04-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-text-06-t-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-text-06-t-expected.png index 86624018..8695456 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-text-06-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-text-06-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-text-07-t-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-text-07-t-expected.png index 912144d..6f8e33e 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-text-07-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-text-07-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-text-08-b-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-text-08-b-expected.png index 601af4c..f57c383 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-text-08-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-text-08-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-tselect-01-b-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-tselect-01-b-expected.png index 8b66d08..b972f06 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-tselect-01-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-tselect-01-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-tselect-02-f-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-tselect-02-f-expected.png index 0a0687e..8fa0279 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-tselect-02-f-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-tselect-02-f-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-tspan-01-b-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-tspan-01-b-expected.png index 108ab5d..50974cc8 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-tspan-01-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-tspan-01-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-ws-01-t-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-ws-01-t-expected.png index d8056fe6..6307340c 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-ws-01-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-ws-01-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-ws-02-t-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-ws-02-t-expected.png index b3d644b..1e0429e 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-ws-02-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/text/text-selection-ws-02-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/transforms/svg-css-transforms-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/transforms/svg-css-transforms-expected.txt index 9602dc8..dc2fd94b 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/transforms/svg-css-transforms-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/transforms/svg-css-transforms-expected.txt
@@ -23,11 +23,11 @@ layer at (28,86) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,67.81) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] LayoutSVGRoot {svg} at (29,109) size 196x175 - LayoutSVGContainer {g} at (29,110) size 196x173 [transform={m=((1.00,0.00)(0.00,1.00)) t=(75.00,25.00)}] - LayoutSVGRect {rect} at (103,111) size 62x62 [stroke={[type=SOLID] [color=#000000] [dash array={1.00, 1.00}]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] - LayoutSVGContainer {g} at (29,110) size 196x173 [transform={m=((2.00,0.00)(0.00,2.00)) t=(0.00,0.00)}] + LayoutSVGContainer {g} at (29,109) size 196x175 [transform={m=((1.00,0.00)(0.00,1.00)) t=(75.00,25.00)}] + LayoutSVGRect {rect} at (103,110) size 62x63 [stroke={[type=SOLID] [color=#000000] [dash array={1.00, 1.00}]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGContainer {g} at (29,109) size 196x175 [transform={m=((2.00,0.00)(0.00,2.00)) t=(0.00,0.00)}] LayoutSVGRect {rect} at (103,110) size 122x123 [stroke={[type=SOLID] [color=#000000] [dash array={1.00, 1.00}]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] - LayoutSVGRect {rect} at (29,110) size 162x173 [transform={m=((0.71,0.71)(-0.71,0.71)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGRect {rect} at (29,109) size 162x175 [transform={m=((0.71,0.71)(-0.71,0.71)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] LayoutText {#text} at (0,0) size 0x0 layer at (28,354) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,335.63) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] @@ -40,7 +40,7 @@ layer at (272,86) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,67.81) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] LayoutSVGRoot {svg} at (273,109) size 162x175 - LayoutSVGRect {rect} at (273,110) size 162x173 [transform={m=((1.41,1.41)(-1.41,1.41)) t=(75.00,25.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGRect {rect} at (273,109) size 162x175 [transform={m=((1.41,1.41)(-1.41,1.41)) t=(75.00,25.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] LayoutText {#text} at (0,0) size 0x0 layer at (272,354) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,335.63) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)]
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-foreignObject-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-foreignObject-expected.txt index e00470d..8c20666 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-foreignObject-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-foreignObject-expected.txt
@@ -17,11 +17,11 @@ LayoutSVGRect {rect} at (0,0) size 361x289 [stroke={[type=SOLID] [color=#008000]}] [x=0.00] [y=0.00] [width=250.00] [height=200.00] LayoutSVGForeignObject {foreignObject} at (260,0) size 250x200 LayoutSVGRoot {svg} at (374,7) size 361x281 - LayoutSVGContainer {g} at (375,7) size 360x281 [transform={m=((3.00,0.26)(0.26,3.02)) t=(0.00,0.00)}] + LayoutSVGContainer {g} at (374,7) size 361x281 [transform={m=((3.00,0.26)(0.26,3.02)) t=(0.00,0.00)}] LayoutSVGText {text} at (0,1) size 83x19 contains 1 chunk(s) LayoutSVGInlineText {#text} at (0,0) size 83x19 chunk 1 text run 1 at (0.00,16.00) startOffset 0 endOffset 14 width 82.20: "This is a text" - LayoutSVGContainer {a} at (382,90) size 297x106 + LayoutSVGContainer {a} at (381,89) size 299x107 LayoutSVGText {text} at (0,20) size 68x19 contains 1 chunk(s) LayoutSVGInlineText {#text} at (0,0) size 68x19 chunk 1 text run 1 at (0.00,35.00) startOffset 0 endOffset 11 width 67.08: "and a link."
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-float-border-padding-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-float-border-padding-expected.txt index e8bc736b..bd838a0e 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-float-border-padding-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-float-border-padding-expected.txt
@@ -12,7 +12,7 @@ LayoutText {#text} at (0,0) size 518x26 text run at (0,0) width 518: "There should be a red, white and blue pattern below this" LayoutSVGRoot (floating) {svg} at (25,149) size 202x202 - LayoutSVGRect {rect} at (54,178) size 145x145 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00] + LayoutSVGRect {rect} at (53,177) size 146x146 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00] LayoutBlockFlow {p} at (0,353.63) size 761.97x26 LayoutText {#text} at (0,0) size 517x26 text run at (0,0) width 517: "There should be a red, white and blue pattern above this"
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/svg-vs-css-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/transforms/svg-vs-css-expected.txt index 1b3ff10..bf9d6de 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/transforms/svg-vs-css-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/svg-vs-css-expected.txt
@@ -32,11 +32,11 @@ layer at (28,86) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,67.81) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] LayoutSVGRoot {svg} at (29,109) size 196x175 - LayoutSVGContainer {g} at (29,110) size 196x173 [transform={m=((1.00,0.00)(0.00,1.00)) t=(75.00,25.00)}] - LayoutSVGRect {rect} at (103,111) size 62x62 [stroke={[type=SOLID] [color=#000000] [dash array={1.00, 1.00}]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] - LayoutSVGContainer {g} at (29,110) size 196x173 [transform={m=((2.00,0.00)(0.00,2.00)) t=(0.00,0.00)}] + LayoutSVGContainer {g} at (29,109) size 196x175 [transform={m=((1.00,0.00)(0.00,1.00)) t=(75.00,25.00)}] + LayoutSVGRect {rect} at (103,110) size 62x63 [stroke={[type=SOLID] [color=#000000] [dash array={1.00, 1.00}]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGContainer {g} at (29,109) size 196x175 [transform={m=((2.00,0.00)(0.00,2.00)) t=(0.00,0.00)}] LayoutSVGRect {rect} at (103,110) size 122x123 [stroke={[type=SOLID] [color=#000000] [dash array={1.00, 1.00}]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] - LayoutSVGRect {rect} at (29,110) size 162x173 [transform={m=((0.71,0.71)(-0.71,0.71)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGRect {rect} at (29,109) size 162x175 [transform={m=((0.71,0.71)(-0.71,0.71)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] LayoutText {#text} at (0,0) size 0x0 layer at (28,354) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,335.63) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] @@ -49,7 +49,7 @@ layer at (272,86) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,67.81) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] LayoutSVGRoot {svg} at (273,109) size 162x175 - LayoutSVGRect {rect} at (273,110) size 162x173 [transform={m=((1.41,1.41)(-1.41,1.41)) t=(75.00,25.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGRect {rect} at (273,109) size 162x175 [transform={m=((1.41,1.41)(-1.41,1.41)) t=(75.00,25.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] LayoutText {#text} at (0,0) size 0x0 layer at (272,354) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,335.63) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] @@ -58,7 +58,7 @@ layer at (516,86) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,67.81) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] LayoutSVGRoot {svg} at (517,109) size 162x175 - LayoutSVGRect {rect} at (517,110) size 162x173 [transform={m=((1.41,1.41)(-1.41,1.41)) t=(75.00,25.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGRect {rect} at (517,109) size 162x175 [transform={m=((1.41,1.41)(-1.41,1.41)) t=(75.00,25.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] LayoutText {#text} at (0,0) size 0x0 layer at (516,354) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,335.63) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)]
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/block/basic/fieldset-stretch-to-legend-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/block/basic/fieldset-stretch-to-legend-expected.png deleted file mode 100644 index cdb888e..0000000 --- a/third_party/WebKit/LayoutTests/platform/win/fast/block/basic/fieldset-stretch-to-legend-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/text-selection-text-05-t-expected.png b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/text-selection-text-05-t-expected.png index c6e181bd..f0d1c938 100644 --- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/text-selection-text-05-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/svg/text-selection-text-05-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/custom/embedding-external-svgs-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/custom/embedding-external-svgs-expected.txt index 2be7cc9f..d32c228 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/custom/embedding-external-svgs-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/svg/custom/embedding-external-svgs-expected.txt
@@ -22,17 +22,17 @@ LayoutSVGRoot {svg:svg} at (91,278) size 31x30 LayoutSVGContainer {svg:g} at (91,278) size 31x30 LayoutSVGPath {svg:polygon} at (104,278) size 5x8 [fill={[type=SOLID] [color=#000000] [opacity=0.04]}] [points="22 0 28 0 27 12 23 12"] - LayoutSVGPath {svg:polygon} at (108,279) size 8x9 [transform={m=((0.87,0.50)(-0.50,0.87)) t=(15.85,-9.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.08]}] [points="22 0 28 0 27 12 23 12"] - LayoutSVGPath {svg:polygon} at (112,283) size 9x8 [transform={m=((0.50,0.87)(-0.87,0.50)) t=(34.15,-9.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.12]}] [points="22 0 28 0 27 12 23 12"] - LayoutSVGPath {svg:polygon} at (114,291) size 8x4 [transform={m=((0.00,1.00)(-1.00,0.00)) t=(50.00,0.00)}] [fill={[type=SOLID] [color=#000000] [opacity=0.16]}] [points="22 0 28 0 27 12 23 12"] - LayoutSVGPath {svg:polygon} at (112,295) size 9x8 [transform={m=((-0.50,0.87)(-0.87,-0.50)) t=(59.15,15.85)}] [fill={[type=SOLID] [color=#000000] [opacity=0.20]}] [points="22 0 28 0 27 12 23 12"] - LayoutSVGPath {svg:polygon} at (108,298) size 8x9 [transform={m=((-0.87,0.50)(-0.50,-0.87)) t=(59.15,34.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.24]}] [points="22 0 28 0 27 12 23 12"] + LayoutSVGPath {svg:polygon} at (108,279) size 9x9 [transform={m=((0.87,0.50)(-0.50,0.87)) t=(15.85,-9.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.08]}] [points="22 0 28 0 27 12 23 12"] + LayoutSVGPath {svg:polygon} at (111,283) size 10x8 [transform={m=((0.50,0.87)(-0.87,0.50)) t=(34.15,-9.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.12]}] [points="22 0 28 0 27 12 23 12"] + LayoutSVGPath {svg:polygon} at (113,291) size 9x4 [transform={m=((0.00,1.00)(-1.00,0.00)) t=(50.00,0.00)}] [fill={[type=SOLID] [color=#000000] [opacity=0.16]}] [points="22 0 28 0 27 12 23 12"] + LayoutSVGPath {svg:polygon} at (111,295) size 10x8 [transform={m=((-0.50,0.87)(-0.87,-0.50)) t=(59.15,15.85)}] [fill={[type=SOLID] [color=#000000] [opacity=0.20]}] [points="22 0 28 0 27 12 23 12"] + LayoutSVGPath {svg:polygon} at (108,298) size 9x9 [transform={m=((-0.87,0.50)(-0.50,-0.87)) t=(59.15,34.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.24]}] [points="22 0 28 0 27 12 23 12"] LayoutSVGPath {svg:polygon} at (104,300) size 5x8 [transform={m=((-1.00,0.00)(-0.00,-1.00)) t=(50.00,50.00)}] [fill={[type=SOLID] [color=#000000] [opacity=0.29]}] [points="22 0 28 0 27 12 23 12"] - LayoutSVGPath {svg:polygon} at (97,298) size 7x9 [transform={m=((-0.87,-0.50)(0.50,-0.87)) t=(34.15,59.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.33]}] [points="22 0 28 0 27 12 23 12"] - LayoutSVGPath {svg:polygon} at (92,295) size 9x8 [transform={m=((-0.50,-0.87)(0.87,-0.50)) t=(15.85,59.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.37]}] [points="22 0 28 0 27 12 23 12"] - LayoutSVGPath {svg:polygon} at (91,291) size 8x4 [transform={m=((-0.00,-1.00)(1.00,-0.00)) t=(0.00,50.00)}] [fill={[type=SOLID] [color=#000000] [opacity=0.41]}] [points="22 0 28 0 27 12 23 12"] - LayoutSVGPath {svg:polygon} at (92,283) size 9x8 [transform={m=((0.50,-0.87)(0.87,0.50)) t=(-9.15,34.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.45]}] [points="22 0 28 0 27 12 23 12"] - LayoutSVGPath {svg:polygon} at (97,279) size 7x9 [transform={m=((0.87,-0.50)(0.50,0.87)) t=(-9.15,15.85)}] [fill={[type=SOLID] [color=#000000] [opacity=0.50]}] [points="22 0 28 0 27 12 23 12"] + LayoutSVGPath {svg:polygon} at (96,298) size 9x9 [transform={m=((-0.87,-0.50)(0.50,-0.87)) t=(34.15,59.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.33]}] [points="22 0 28 0 27 12 23 12"] + LayoutSVGPath {svg:polygon} at (92,295) size 10x8 [transform={m=((-0.50,-0.87)(0.87,-0.50)) t=(15.85,59.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.37]}] [points="22 0 28 0 27 12 23 12"] + LayoutSVGPath {svg:polygon} at (91,291) size 9x4 [transform={m=((-0.00,-1.00)(1.00,-0.00)) t=(0.00,50.00)}] [fill={[type=SOLID] [color=#000000] [opacity=0.41]}] [points="22 0 28 0 27 12 23 12"] + LayoutSVGPath {svg:polygon} at (92,283) size 10x8 [transform={m=((0.50,-0.87)(0.87,0.50)) t=(-9.15,34.15)}] [fill={[type=SOLID] [color=#000000] [opacity=0.45]}] [points="22 0 28 0 27 12 23 12"] + LayoutSVGPath {svg:polygon} at (96,279) size 9x9 [transform={m=((0.87,-0.50)(0.50,0.87)) t=(-9.15,15.85)}] [fill={[type=SOLID] [color=#000000] [opacity=0.50]}] [points="22 0 28 0 27 12 23 12"] LayoutText {#text} at (0,0) size 0x0 layer at (290,16) size 40x40 LayoutEmbeddedObject {embed} at (239.69,0) size 40x40
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/bbox-with-glyph-overflow-zoomed-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/text/bbox-with-glyph-overflow-zoomed-expected.txt index 929fbd83..3231556 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/bbox-with-glyph-overflow-zoomed-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/bbox-with-glyph-overflow-zoomed-expected.txt
@@ -48,6 +48,6 @@ chunk 1 text run 1 at (20.00,75.00) startOffset 0 endOffset 5 width 32.06: "'faQ'" LayoutSVGRect {rect} at (45,63) size 155x27 [stroke={[type=SOLID] [color=#008000]}] [fill={[type=SOLID] [color=#00000000]}] [x=17.77] [y=9.45] [width=84.42] [height=13.33] LayoutSVGRect {rect} at (45,98) size 124x50 [stroke={[type=SOLID] [color=#008000]}] [fill={[type=SOLID] [color=#00000000]}] [x=17.77] [y=28.89] [width=67.20] [height=26.11] - LayoutSVGRect {rect} at (49,157) size 60x33 [stroke={[type=SOLID] [color=#008000]}] [fill={[type=SOLID] [color=#00000000]}] [x=20.00] [y=61.67] [width=32.05] [height=16.66] + LayoutSVGRect {rect} at (49,157) size 61x33 [stroke={[type=SOLID] [color=#008000]}] [fill={[type=SOLID] [color=#00000000]}] [x=20.00] [y=61.67] [width=32.05] [height=16.66] LayoutText {#text} at (0,0) size 0x0 LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/small-fonts-in-html5-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/text/small-fonts-in-html5-expected.txt index f03c7ec..e932f11d 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/small-fonts-in-html5-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/small-fonts-in-html5-expected.txt
@@ -8,7 +8,7 @@ text run at (0,0) width 470: "Small fonts in HTML5/inline SVG" LayoutBlockFlow (anonymous) at (0,58.44) size 784x506 LayoutSVGRoot {svg} at (8,79) size 502x503 - LayoutSVGContainer {g} at (159,268) size 94x20 [transform={m=((400.00,0.00)(0.00,400.00)) t=(0.00,0.00)}] + LayoutSVGContainer {g} at (159,267) size 94x21 [transform={m=((400.00,0.00)(0.00,400.00)) t=(0.00,0.00)}] LayoutSVGText {text} at (0,0) size 1x1 contains 1 chunk(s) LayoutSVGInlineText {#text} at (0,0) size 1x1 chunk 1 (middle anchor) text run 1 at (0.38,0.50) startOffset 0 endOffset 12 width 0.24: "Test passed."
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-align-01-b-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-align-01-b-expected.png index 87105df..ab226ec 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-align-01-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-align-01-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-align-02-b-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-align-02-b-expected.png index 90133b5..3bda9d40 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-align-02-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-align-02-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-align-05-b-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-align-05-b-expected.png index 07d841e..3c815b2f 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-align-05-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-align-05-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-deco-01-b-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-deco-01-b-expected.png index 2e25adc9..804219fc 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-deco-01-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-deco-01-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-fonts-01-t-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-fonts-01-t-expected.png index 1390a9735..80e3b4f 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-fonts-01-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-fonts-01-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-fonts-02-t-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-fonts-02-t-expected.png index 6c0d203..c0afa3dc 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-fonts-02-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-fonts-02-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-intro-05-t-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-intro-05-t-expected.png index 925414c4..9d7489e 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-intro-05-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-intro-05-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-text-03-b-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-text-03-b-expected.png index 4fc129c..e342ffc45 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-text-03-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-text-03-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-text-04-t-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-text-04-t-expected.png index babd47b9..d1682faa 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-text-04-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-text-04-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-text-06-t-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-text-06-t-expected.png index 686796e..7f4e841 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-text-06-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-text-06-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-text-07-t-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-text-07-t-expected.png index 65e6bf3e..9e942c952 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-text-07-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-text-07-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-text-08-b-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-text-08-b-expected.png index 730fb651..302f9ccd 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-text-08-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-text-08-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-tselect-01-b-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-tselect-01-b-expected.png index 9678240b..ad9936b 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-tselect-01-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-tselect-01-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-tselect-02-f-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-tselect-02-f-expected.png index 8821c24..b024551 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-tselect-02-f-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-tselect-02-f-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-tspan-01-b-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-tspan-01-b-expected.png index c467549..52498f6 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-tspan-01-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-tspan-01-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-ws-01-t-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-ws-01-t-expected.png index af035fc..21fae70 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-ws-01-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-ws-01-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-ws-02-t-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-ws-02-t-expected.png index 566a8de..f0d2596 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-ws-02-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/text/text-selection-ws-02-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/transforms/svg-css-transforms-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/transforms/svg-css-transforms-expected.txt index 29ab8c3d..67734f1 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/transforms/svg-css-transforms-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/svg/transforms/svg-css-transforms-expected.txt
@@ -23,11 +23,11 @@ layer at (28,85) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,66.81) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] LayoutSVGRoot {svg} at (29,108) size 196x175 - LayoutSVGContainer {g} at (29,109) size 196x173 [transform={m=((1.00,0.00)(0.00,1.00)) t=(75.00,25.00)}] - LayoutSVGRect {rect} at (103,110) size 62x62 [stroke={[type=SOLID] [color=#000000] [dash array={1.00, 1.00}]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] - LayoutSVGContainer {g} at (29,109) size 196x173 [transform={m=((2.00,0.00)(0.00,2.00)) t=(0.00,0.00)}] + LayoutSVGContainer {g} at (29,108) size 196x175 [transform={m=((1.00,0.00)(0.00,1.00)) t=(75.00,25.00)}] + LayoutSVGRect {rect} at (103,109) size 62x63 [stroke={[type=SOLID] [color=#000000] [dash array={1.00, 1.00}]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGContainer {g} at (29,108) size 196x175 [transform={m=((2.00,0.00)(0.00,2.00)) t=(0.00,0.00)}] LayoutSVGRect {rect} at (103,109) size 122x123 [stroke={[type=SOLID] [color=#000000] [dash array={1.00, 1.00}]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] - LayoutSVGRect {rect} at (29,109) size 162x173 [transform={m=((0.71,0.71)(-0.71,0.71)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGRect {rect} at (29,108) size 162x175 [transform={m=((0.71,0.71)(-0.71,0.71)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] LayoutText {#text} at (0,0) size 0x0 layer at (28,352) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,333.63) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] @@ -40,7 +40,7 @@ layer at (272,85) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,66.81) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] LayoutSVGRoot {svg} at (273,108) size 162x175 - LayoutSVGRect {rect} at (273,109) size 162x173 [transform={m=((1.41,1.41)(-1.41,1.41)) t=(75.00,25.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGRect {rect} at (273,108) size 162x175 [transform={m=((1.41,1.41)(-1.41,1.41)) t=(75.00,25.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] LayoutText {#text} at (0,0) size 0x0 layer at (272,352) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,333.63) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)]
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-foreignObject-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-foreignObject-expected.txt index 1e6882cf..9326a0b 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-foreignObject-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-foreignObject-expected.txt
@@ -17,11 +17,11 @@ LayoutSVGRect {rect} at (0,0) size 361x289 [stroke={[type=SOLID] [color=#008000]}] [x=0.00] [y=0.00] [width=250.00] [height=200.00] LayoutSVGForeignObject {foreignObject} at (260,0) size 250x200 LayoutSVGRoot {svg} at (374,7) size 361x281 - LayoutSVGContainer {g} at (375,7) size 360x281 [transform={m=((3.00,0.26)(0.26,3.02)) t=(0.00,0.00)}] + LayoutSVGContainer {g} at (374,7) size 361x281 [transform={m=((3.00,0.26)(0.26,3.02)) t=(0.00,0.00)}] LayoutSVGText {text} at (0,1) size 83x19 contains 1 chunk(s) LayoutSVGInlineText {#text} at (0,0) size 83x18 chunk 1 text run 1 at (0.00,16.00) startOffset 0 endOffset 14 width 82.20: "This is a text" - LayoutSVGContainer {a} at (382,90) size 297x103 + LayoutSVGContainer {a} at (381,89) size 299x104 LayoutSVGText {text} at (0,20) size 68x19 contains 1 chunk(s) LayoutSVGInlineText {#text} at (0,0) size 68x18 chunk 1 text run 1 at (0.00,35.00) startOffset 0 endOffset 11 width 67.08: "and a link."
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-float-border-padding-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-float-border-padding-expected.txt index 54bd46d..f7acd8f 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-float-border-padding-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-float-border-padding-expected.txt
@@ -12,7 +12,7 @@ LayoutText {#text} at (0,0) size 518x26 text run at (0,0) width 518: "There should be a red, white and blue pattern below this" LayoutSVGRoot (floating) {svg} at (25,152) size 202x202 - LayoutSVGRect {rect} at (54,181) size 145x145 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00] + LayoutSVGRect {rect} at (53,180) size 146x146 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00] LayoutBlockFlow {p} at (0,356.63) size 761.97x27 LayoutText {#text} at (0,0) size 517x26 text run at (0,0) width 517: "There should be a red, white and blue pattern above this"
diff --git a/third_party/WebKit/LayoutTests/platform/win/transforms/svg-vs-css-expected.txt b/third_party/WebKit/LayoutTests/platform/win/transforms/svg-vs-css-expected.txt index 25b0f52..2be9900 100644 --- a/third_party/WebKit/LayoutTests/platform/win/transforms/svg-vs-css-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/transforms/svg-vs-css-expected.txt
@@ -32,11 +32,11 @@ layer at (28,85) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,66.81) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] LayoutSVGRoot {svg} at (29,108) size 196x175 - LayoutSVGContainer {g} at (29,109) size 196x173 [transform={m=((1.00,0.00)(0.00,1.00)) t=(75.00,25.00)}] - LayoutSVGRect {rect} at (103,110) size 62x62 [stroke={[type=SOLID] [color=#000000] [dash array={1.00, 1.00}]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] - LayoutSVGContainer {g} at (29,109) size 196x173 [transform={m=((2.00,0.00)(0.00,2.00)) t=(0.00,0.00)}] + LayoutSVGContainer {g} at (29,108) size 196x175 [transform={m=((1.00,0.00)(0.00,1.00)) t=(75.00,25.00)}] + LayoutSVGRect {rect} at (103,109) size 62x63 [stroke={[type=SOLID] [color=#000000] [dash array={1.00, 1.00}]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGContainer {g} at (29,108) size 196x175 [transform={m=((2.00,0.00)(0.00,2.00)) t=(0.00,0.00)}] LayoutSVGRect {rect} at (103,109) size 122x123 [stroke={[type=SOLID] [color=#000000] [dash array={1.00, 1.00}]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] - LayoutSVGRect {rect} at (29,109) size 162x173 [transform={m=((0.71,0.71)(-0.71,0.71)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGRect {rect} at (29,108) size 162x175 [transform={m=((0.71,0.71)(-0.71,0.71)) t=(0.00,0.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] LayoutText {#text} at (0,0) size 0x0 layer at (28,352) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,333.63) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] @@ -49,7 +49,7 @@ layer at (272,85) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,66.81) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] LayoutSVGRoot {svg} at (273,108) size 162x175 - LayoutSVGRect {rect} at (273,109) size 162x173 [transform={m=((1.41,1.41)(-1.41,1.41)) t=(75.00,25.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGRect {rect} at (273,108) size 162x175 [transform={m=((1.41,1.41)(-1.41,1.41)) t=(75.00,25.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] LayoutText {#text} at (0,0) size 0x0 layer at (272,352) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,333.63) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] @@ -58,7 +58,7 @@ layer at (516,85) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,66.81) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)] LayoutSVGRoot {svg} at (517,108) size 162x175 - LayoutSVGRect {rect} at (517,109) size 162x173 [transform={m=((1.41,1.41)(-1.41,1.41)) t=(75.00,25.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] + LayoutSVGRect {rect} at (517,108) size 162x175 [transform={m=((1.41,1.41)(-1.41,1.41)) t=(75.00,25.00)}] [stroke={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=60.00] [height=60.00] LayoutText {#text} at (0,0) size 0x0 layer at (516,352) size 200x200 LayoutBlockFlow (relative positioned) {div} at (10,333.63) size 200x200 [bgcolor=#C0C0C0] [border: (1px solid #000000)]
diff --git a/third_party/WebKit/LayoutTests/platform/win7/svg/text/bbox-with-glyph-overflow-zoomed-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/svg/text/bbox-with-glyph-overflow-zoomed-expected.txt index 954d7238..42adccd 100644 --- a/third_party/WebKit/LayoutTests/platform/win7/svg/text/bbox-with-glyph-overflow-zoomed-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win7/svg/text/bbox-with-glyph-overflow-zoomed-expected.txt
@@ -48,6 +48,6 @@ chunk 1 text run 1 at (20.00,75.00) startOffset 0 endOffset 5 width 32.06: "'faQ'" LayoutSVGRect {rect} at (45,63) size 155x27 [stroke={[type=SOLID] [color=#008000]}] [fill={[type=SOLID] [color=#00000000]}] [x=17.77] [y=9.45] [width=84.42] [height=13.33] LayoutSVGRect {rect} at (45,98) size 124x50 [stroke={[type=SOLID] [color=#008000]}] [fill={[type=SOLID] [color=#00000000]}] [x=17.77] [y=28.89] [width=67.20] [height=26.11] - LayoutSVGRect {rect} at (49,157) size 63x33 [stroke={[type=SOLID] [color=#008000]}] [fill={[type=SOLID] [color=#00000000]}] [x=20.00] [y=61.67] [width=33.50] [height=16.66] + LayoutSVGRect {rect} at (49,157) size 64x33 [stroke={[type=SOLID] [color=#008000]}] [fill={[type=SOLID] [color=#00000000]}] [x=20.00] [y=61.67] [width=33.50] [height=16.66] LayoutText {#text} at (0,0) size 0x0 LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win7/svg/text/text-selection-fonts-01-t-expected.png b/third_party/WebKit/LayoutTests/platform/win7/svg/text/text-selection-fonts-01-t-expected.png index dbfe3cd..b6df241 100644 --- a/third_party/WebKit/LayoutTests/platform/win7/svg/text/text-selection-fonts-01-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win7/svg/text/text-selection-fonts-01-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/svg/text/text-selection-intro-05-t-expected.png b/third_party/WebKit/LayoutTests/platform/win7/svg/text/text-selection-intro-05-t-expected.png index e42c65d..9052f05 100644 --- a/third_party/WebKit/LayoutTests/platform/win7/svg/text/text-selection-intro-05-t-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win7/svg/text/text-selection-intro-05-t-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/svg/text/text-selection-text-08-b-expected.png b/third_party/WebKit/LayoutTests/platform/win7/svg/text/text-selection-text-08-b-expected.png index ed8e70a4..55a1f35a 100644 --- a/third_party/WebKit/LayoutTests/platform/win7/svg/text/text-selection-text-08-b-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win7/svg/text/text-selection-text-08-b-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/zoom/page/zoom-clip-path-expected.txt b/third_party/WebKit/LayoutTests/svg/zoom/page/zoom-clip-path-expected.txt index d6659a0..6d443d5a 100644 --- a/third_party/WebKit/LayoutTests/svg/zoom/page/zoom-clip-path-expected.txt +++ b/third_party/WebKit/LayoutTests/svg/zoom/page/zoom-clip-path-expected.txt
@@ -9,12 +9,12 @@ LayoutSVGRect {rect} at (16,16) size 105x105 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=50.00] [height=50.00] LayoutSVGResourceClipper {clipPath} [id="clip2"] [clipPathUnits=userSpaceOnUse] LayoutSVGRect {rect} at (16,16) size 105x105 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=50.00] [height=50.00] - LayoutSVGRect {rect} at (120,120) size 104x104 [fill={[type=SOLID] [color=#000000]}] [x=50.00] [y=50.00] [width=50.00] [height=50.00] + LayoutSVGRect {rect} at (119,119) size 105x105 [fill={[type=SOLID] [color=#000000]}] [x=50.00] [y=50.00] [width=50.00] [height=50.00] LayoutSVGResourceClipper {clipPath} [id="clip3"] [clipPathUnits=objectBoundingBox] - LayoutSVGRect {rect} at (16,16) size 2x2 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=0.50] [height=0.50] + LayoutSVGRect {rect} at (16,16) size 3x3 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=0.50] [height=0.50] LayoutSVGResourceClipper {clipPath} [id="clip4"] [clipPathUnits=objectBoundingBox] - LayoutSVGRect {rect} at (16,16) size 2x2 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=0.50] [height=0.50] - LayoutSVGRect {rect} at (17,17) size 2x2 [fill={[type=SOLID] [color=#000000]}] [x=0.50] [y=0.50] [width=0.50] [height=0.50] + LayoutSVGRect {rect} at (16,16) size 3x3 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=0.50] [height=0.50] + LayoutSVGRect {rect} at (17,17) size 3x3 [fill={[type=SOLID] [color=#000000]}] [x=0.50] [y=0.50] [width=0.50] [height=0.50] LayoutText {#text} at (0,0) size 0x0 LayoutText {#text} at (0,0) size 0x0 LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt index 5178fedf..5c55e47 100644 --- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -532,6 +532,14 @@ getter data method constructor method initCompositionEvent +interface ConstantSourceNode : AudioSourceNode + attribute @@toStringTag + getter offset + getter onended + method constructor + method start + method stop + setter onended interface ConvolverNode : AudioNode attribute @@toStringTag getter buffer
diff --git a/third_party/WebKit/LayoutTests/webaudio/audioparam-nominal-range-expected.txt b/third_party/WebKit/LayoutTests/webaudio/audioparam-nominal-range-expected.txt index 078e8c3e..a971d24 100644 --- a/third_party/WebKit/LayoutTests/webaudio/audioparam-nominal-range-expected.txt +++ b/third_party/WebKit/LayoutTests/webaudio/audioparam-nominal-range-expected.txt
@@ -1,25 +1,25 @@ -CONSOLE WARNING: line 387: Delay.delayTime.value -1 outside nominal range [0, 1.5]; value will be clamped. -CONSOLE WARNING: line 396: Delay.delayTime.value 4 outside nominal range [0, 1.5]; value will be clamped. -CONSOLE WARNING: line 387: StereoPanner.pan.value -3 outside nominal range [-1, 1]; value will be clamped. -CONSOLE WARNING: line 396: StereoPanner.pan.value 3 outside nominal range [-1, 1]; value will be clamped. -CONSOLE WARNING: line 387: DynamicsCompressor.threshold.value -201 outside nominal range [-100, 0]; value will be clamped. -CONSOLE WARNING: line 396: DynamicsCompressor.threshold.value 1 outside nominal range [-100, 0]; value will be clamped. -CONSOLE WARNING: line 387: DynamicsCompressor.knee.value -1 outside nominal range [0, 40]; value will be clamped. -CONSOLE WARNING: line 396: DynamicsCompressor.knee.value 81 outside nominal range [0, 40]; value will be clamped. -CONSOLE WARNING: line 396: DynamicsCompressor.ratio.value 41 outside nominal range [1, 20]; value will be clamped. -CONSOLE WARNING: line 387: DynamicsCompressor.attack.value -1 outside nominal range [0, 1]; value will be clamped. -CONSOLE WARNING: line 396: DynamicsCompressor.attack.value 3 outside nominal range [0, 1]; value will be clamped. -CONSOLE WARNING: line 387: DynamicsCompressor.release.value -1 outside nominal range [0, 1]; value will be clamped. -CONSOLE WARNING: line 396: DynamicsCompressor.release.value 3 outside nominal range [0, 1]; value will be clamped. -CONSOLE WARNING: line 387: BiquadFilter.frequency.value -1 outside nominal range [0, 24000]; value will be clamped. -CONSOLE WARNING: line 396: BiquadFilter.frequency.value 48001 outside nominal range [0, 24000]; value will be clamped. -CONSOLE WARNING: line 387: Oscillator.frequency.value -48001 outside nominal range [-24000, 24000]; value will be clamped. -CONSOLE WARNING: line 396: Oscillator.frequency.value 48001 outside nominal range [-24000, 24000]; value will be clamped. -CONSOLE WARNING: line 316: Delay.delayTime.setValueAtTime value -1 outside nominal range [0, 1]; value will be clamped. -CONSOLE WARNING: line 317: Delay.delayTime.linearRampToValueAtTime value 2 outside nominal range [0, 1]; value will be clamped. -CONSOLE WARNING: line 318: Delay.delayTime.exponentialRampToValue value 3 outside nominal range [0, 1]; value will be clamped. -CONSOLE WARNING: line 319: Delay.delayTime.setTargetAtTime value -1 outside nominal range [0, 1]; value will be clamped. -CONSOLE WARNING: line 320: Delay.delayTime.setValueCurveAtTime value 1.5 outside nominal range [0, 1]; value will be clamped. +CONSOLE WARNING: line 396: Delay.delayTime.value -1 outside nominal range [0, 1.5]; value will be clamped. +CONSOLE WARNING: line 405: Delay.delayTime.value 4 outside nominal range [0, 1.5]; value will be clamped. +CONSOLE WARNING: line 396: StereoPanner.pan.value -3 outside nominal range [-1, 1]; value will be clamped. +CONSOLE WARNING: line 405: StereoPanner.pan.value 3 outside nominal range [-1, 1]; value will be clamped. +CONSOLE WARNING: line 396: DynamicsCompressor.threshold.value -201 outside nominal range [-100, 0]; value will be clamped. +CONSOLE WARNING: line 405: DynamicsCompressor.threshold.value 1 outside nominal range [-100, 0]; value will be clamped. +CONSOLE WARNING: line 396: DynamicsCompressor.knee.value -1 outside nominal range [0, 40]; value will be clamped. +CONSOLE WARNING: line 405: DynamicsCompressor.knee.value 81 outside nominal range [0, 40]; value will be clamped. +CONSOLE WARNING: line 405: DynamicsCompressor.ratio.value 41 outside nominal range [1, 20]; value will be clamped. +CONSOLE WARNING: line 396: DynamicsCompressor.attack.value -1 outside nominal range [0, 1]; value will be clamped. +CONSOLE WARNING: line 405: DynamicsCompressor.attack.value 3 outside nominal range [0, 1]; value will be clamped. +CONSOLE WARNING: line 396: DynamicsCompressor.release.value -1 outside nominal range [0, 1]; value will be clamped. +CONSOLE WARNING: line 405: DynamicsCompressor.release.value 3 outside nominal range [0, 1]; value will be clamped. +CONSOLE WARNING: line 396: BiquadFilter.frequency.value -1 outside nominal range [0, 24000]; value will be clamped. +CONSOLE WARNING: line 405: BiquadFilter.frequency.value 48001 outside nominal range [0, 24000]; value will be clamped. +CONSOLE WARNING: line 396: Oscillator.frequency.value -48001 outside nominal range [-24000, 24000]; value will be clamped. +CONSOLE WARNING: line 405: Oscillator.frequency.value 48001 outside nominal range [-24000, 24000]; value will be clamped. +CONSOLE WARNING: line 325: Delay.delayTime.setValueAtTime value -1 outside nominal range [0, 1]; value will be clamped. +CONSOLE WARNING: line 326: Delay.delayTime.linearRampToValueAtTime value 2 outside nominal range [0, 1]; value will be clamped. +CONSOLE WARNING: line 327: Delay.delayTime.exponentialRampToValue value 3 outside nominal range [0, 1]; value will be clamped. +CONSOLE WARNING: line 328: Delay.delayTime.setTargetAtTime value -1 outside nominal range [0, 1]; value will be clamped. +CONSOLE WARNING: line 329: Delay.delayTime.setValueCurveAtTime value 1.5 outside nominal range [0, 1]; value will be clamped. Test AudioParam Nominal Range Values. On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". @@ -200,6 +200,14 @@ PASS PannerNode.orientationZ.maxValue is read-only. PASS Nominal ranges for AudioParam(s) of PannerNode are correct. +PASS ConstantSourceNode.offset.minValue is equal to -3.4028234663852886e+38. +PASS ConstantSourceNode.offset.maxValue is equal to 3.4028234663852886e+38. +PASS ConstantSourceNode.offset.minValue = Math.PI is not equal to 3.141592653589793. +PASS ConstantSourceNode.offset.minValue is read-only. +PASS ConstantSourceNode.offset.maxValue = Math.PI is not equal to 3.141592653589793. +PASS ConstantSourceNode.offset.maxValue is read-only. +PASS Nominal ranges for AudioParam(s) of ConstantSourceNode are correct. + PASS AudioBuffer has no AudioParams as expected. PASS IIRFilterNode has no AudioParams as expected.
diff --git a/third_party/WebKit/LayoutTests/webaudio/audioparam-nominal-range.html b/third_party/WebKit/LayoutTests/webaudio/audioparam-nominal-range.html index 5d322f8..98d02eb 100644 --- a/third_party/WebKit/LayoutTests/webaudio/audioparam-nominal-range.html +++ b/third_party/WebKit/LayoutTests/webaudio/audioparam-nominal-range.html
@@ -173,6 +173,15 @@ maxValue: mostPositiveFloat, } }, + }, { + creator: "createConstantSource", + args: [], + limits: { + offset: { + minValue: -mostPositiveFloat, + maxValue: mostPositiveFloat + } + } }, // These nodes don't have AudioParams, but we want to test them anyway. Any arguments for the // constructor are pretty much arbitrary; they just need to be valid.
diff --git a/third_party/WebKit/LayoutTests/webaudio/constant-source-basic.html b/third_party/WebKit/LayoutTests/webaudio/constant-source-basic.html new file mode 100644 index 0000000..2ea5b95 --- /dev/null +++ b/third_party/WebKit/LayoutTests/webaudio/constant-source-basic.html
@@ -0,0 +1,88 @@ +<!doctype html> +<html> + <head> + <title>Basic ConstantSourceNode Tests</title> + <script src="../resources/testharness.js"></script> + <script src="../resources/testharnessreport.js"></script> + <script src="resources/audio-testing.js"></script> + </head> + + <body> + <script> + var context = new AudioContext(); + + var audit = Audit.createTaskRunner(); + + audit.defineTask("createConstantSource()", function (taskDone) { + var node; + var success = true; + + success = Should("node = context.createConstantSource()", function () { + node = context.createConstantSource(); + }).notThrow(); + success = Should("node instance of ConstantSourceNode", + node instanceof ConstantSourceNode) + .beEqualTo(true) && success; + + success = verifyNodeDefaults(node) && success; + + Should("createConstantSource()", success) + .summarize( + "correctly created", + "incorrectly created"); + + taskDone(); + }); + + audit.defineTask("new ConstantSourceNode()", function (taskDone) { + var node; + var success = true; + + success = Should("node = new ConstantSourceNode()", function () { + node = new ConstantSourceNode(context); + }).notThrow(); + success = Should("node instance of ConstantSourceNode", + node instanceof ConstantSourceNode) + .beEqualTo(true) && success; + + + success = verifyNodeDefaults(node) && success; + + Should("new ConstantSourceNode(context)", success) + .summarize( + "correctly created", + "incorrectly created"); + + taskDone(); + }); + + function verifyNodeDefaults(node) { + var success = true; + + success = Should("node.numberOfInputs", node.numberOfInputs) + .beEqualTo(0); + success = Should("node.numberOfOutputs", node.numberOfOutputs) + .beEqualTo(1) && success; + success = Should("node.channelCount", node.channelCount) + .beEqualTo(2) && success; + success = Should("node.channelCountMode", node.channelCountMode) + .beEqualTo("max") && success; + success = Should("node.channelInterpretation", node.channelInterpretation) + .beEqualTo("speakers") && success; + + success = Should("node.offset.value", node.offset.value) + .beEqualTo(1) && success; + success = Should("node.offset.defaultValue", node.offset.defaultValue) + .beEqualTo(1) && success; + success = Should("node.offset.minValue", node.offset.minValue) + .beEqualTo(Math.fround(-3.4028235e38)) && success; + success = Should("node.offset.maxValue", node.offset.maxValue) + .beEqualTo(Math.fround(3.4028235e38)) && success; + + return success; + } + + audit.runTasks(); + </script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/constant-source-onended.html b/third_party/WebKit/LayoutTests/webaudio/constant-source-onended.html new file mode 100644 index 0000000..fab29150f --- /dev/null +++ b/third_party/WebKit/LayoutTests/webaudio/constant-source-onended.html
@@ -0,0 +1,39 @@ +<!doctype html> +<html> + <head> + <title>Test ConstantSourceNode onended</title> + <script src="../resources/testharness.js"></script> + <script src="../resources/testharnessreport.js"></script> + <script src="resources/audio-testing.js"></script> + </head> + + <body> + <script> + var sampleRate = 44100.0; + // Number of frames that the source will run; fairly arbitrary + var numberOfFrames = 32; + // Number of frames to render; arbitrary, but should be larger than + // numberOfFrames; + var renderFrames = 16 * numberOfFrames; + + var context = new OfflineAudioContext(1, renderFrames, sampleRate); + var src = new ConstantSourceNode(context); + src.connect(context.destination); + + var tester = async_test("ConstantSourceNode onended event fired"); + + src.onended = function () { + tester.step(function () { + assert_true(true, "ConstantSourceNode.onended fired"); + }); + tester.done(); + }; + + src.start(); + src.stop(numberOfFrames / context.sampleRate); + + context.startRendering(); + + </script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/constant-source-output.html b/third_party/WebKit/LayoutTests/webaudio/constant-source-output.html new file mode 100644 index 0000000..4873b7b --- /dev/null +++ b/third_party/WebKit/LayoutTests/webaudio/constant-source-output.html
@@ -0,0 +1,181 @@ +<!doctype html> +<html> + <head> + <title>Test ConstantSourceNode Output</title> + <script src="../resources/testharness.js"></script> + <script src="../resources/testharnessreport.js"></script> + <script src="resources/audio-testing.js"></script> + <script src="resources/audioparam-testing.js"></script> + </head> + + <body> + <script> + var sampleRate = 48000; + var renderDuration = 0.125; + var renderFrames = sampleRate * renderDuration; + + var audit = Audit.createTaskRunner(); + + audit.defineTask("constant source", function (taskDone) { + // Verify a constant source outputs the correct (fixed) constant. + var context = new OfflineAudioContext(1, renderFrames, sampleRate); + var node = new ConstantSourceNode(context, { + offset: 0.5 + }); + node.connect(context.destination); + node.start(); + + context.startRendering().then(function (buffer) { + var actual = buffer.getChannelData(0); + var expected = new Float32Array(actual.length); + expected.fill(node.offset.value); + + Should("ConstantSourceNode({offset: 0.5})", actual) + .beEqualToArray(expected); + }).then(taskDone); + }); + + audit.defineTask("start/stop", function (taskDone) { + // Verify a constant source starts and stops at the correct time and has + // the correct (fixed) value. + var context = new OfflineAudioContext(1, renderFrames, sampleRate); + var node = new ConstantSourceNode(context, { + offset: 1 + }); + node.connect(context.destination); + + var startFrame = 10; + var stopFrame = 300; + + node.start(startFrame / context.sampleRate); + node.stop(stopFrame / context.sampleRate); + + context.startRendering().then(function (buffer) { + var actual = buffer.getChannelData(0); + var expected = new Float32Array(actual.length); + // The expected output is all 1s from start to stop time. + expected.fill(0); + + for (var k = startFrame; k < stopFrame; ++k) { + expected[k] = node.offset.value; + } + + var success = Should("ConstantSourceNode frames [0, " + + startFrame + ")", + actual.slice(0, startFrame)) + .beConstantValueOf(0); + + success = Should("ConstantSourceNode frames [" + startFrame + + ", " + + stopFrame + ")", + actual.slice(startFrame, stopFrame)) + .beConstantValueOf(1) && success; + + success = Should("ConstantSourceNode frames [" + stopFrame + ", " + + renderFrames + ")", + actual.slice(stopFrame)) + .beConstantValueOf(0) && success; + + Should("ConstantSourceNode started and stopped", success) + .summarize( + "at the correct times with the correct values", + "with the incorrect times or values"); + }).then(taskDone); + + }); + + audit.defineTask("basic automation", function (taskDone) { + // Verify that automation works as expected. + var context = new OfflineAudioContext(1, renderFrames, sampleRate); + var source = context.createConstantSource(); + source.connect(context.destination); + + var rampEndTime = renderDuration / 2; + source.offset.setValueAtTime(0.5, 0); + source.offset.linearRampToValueAtTime(1, rampEndTime); + + source.start(); + + context.startRendering() + .then(function (buffer) { + var actual = buffer.getChannelData(0); + var expected = createLinearRampArray(0, rampEndTime, 0.5, 1, + context.sampleRate); + + var rampEndFrame = Math.ceil(rampEndTime * context.sampleRate); + var success = Should("ConstantSourceNode.linearRamp(1, 0.5)", + actual.slice(0, rampEndFrame)) + .beCloseToArray(expected, { + // Experimentally determined threshold.. + relativeThreshold: 7.1610e-7 + }); + + success = Should("ConstantSourceNode after ramp", + actual.slice(rampEndFrame)) + .beConstantValueOf(1) && success; + + Should("ConstantSourceNode automation", success) + .summarize( + "produced the correct values", + "did not produce the correct values"); + }) + .then(taskDone); + }); + + audit.defineTask("connected audioparam", function (taskDone) { + // Verify the constant source output with connected AudioParam produces + // the correct output. + var context = new OfflineAudioContext(2, renderFrames, sampleRate) + context.destination.channelInterpretation = "discrete"; + var source = new ConstantSourceNode(context, { + offset: 1 + }); + var osc = context.createOscillator(); + var merger = context.createChannelMerger(2); + merger.connect(context.destination); + + source.connect(merger, 0, 0); + osc.connect(merger, 0, 1); + osc.connect(source.offset); + + osc.start(); + var sourceStartFrame = 10; + source.start(sourceStartFrame / context.sampleRate); + + context.startRendering() + .then(function (buffer) { + // Channel 0 and 1 should be identical, except channel 0 (the + // source) is silent at the beginning. + var actual = buffer.getChannelData(0); + var expected = buffer.getChannelData(1); + // The expected output should be oscillator + 1 because offset + // is 1. + expected = expected.map(x => 1 + x); + var success = true; + + // The initial part of the output should be silent because the + // source node hasn't started yet. + success = Should("ConstantSourceNode frames [0, " + + sourceStartFrame + ")", actual.slice(0, sourceStartFrame) + ) + .beConstantValueOf(0); + // The rest of the output should be the same as the oscillator (in + // channel 1) + success = Should("ConstantSourceNode frames [" + + sourceStartFrame + ", " + renderFrames + ")", + actual.slice(sourceStartFrame)) + .beCloseToArray(expected.slice(sourceStartFrame), 0); + + Should("ConstantSourceNode with connected AudioParam", + success) + .summarize( + "had the expected output", + "did not have the expected output"); + }) + .then(taskDone); + }); + + audit.runTasks(); + </script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/webaudio/constructor/constantsource.html b/third_party/WebKit/LayoutTests/webaudio/constructor/constantsource.html new file mode 100644 index 0000000..a705de5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/webaudio/constructor/constantsource.html
@@ -0,0 +1,74 @@ +<!doctype html> +<html> + <head> + <title>Test Constructor: ConstantSource</title> + <script src="../../resources/testharness.js"></script> + <script src="../../resources/testharnessreport.js"></script> + <script src="../resources/audio-testing.js"></script> + </head> + + <body> + <script> + var context; + + var audit = Audit.createTaskRunner(); + + audit.defineTask("initialize", function (taskDone) { + Should("context = new OfflineAudioContext(...)", function () { + context = new OfflineAudioContext(1, 1, 48000); + }).notThrow(); + taskDone(); + }); + + audit.defineTask("invalid constructor", function (taskDone) { + var node; + var success = true; + + succes = Should("new ConstantSourceNode()", function () { + node = new ConstantSourceNode(); + }).throw("TypeError"); + success = Should("new ConstantSourceNode(1)", function () { + node = new ConstantSourceNode(1); + }).throw("TypeError") && success; + success = Should("new ConstantSourceNode(context, 42)", function () { + node = new ConstantSourceNode(context, 42); + }).throw("TypeError") && success; + + Should("*** Invalid constructors", success) + .summarize( + "correctly threw errors", + "did not throw errors in all cases"); + taskDone(); + }); + + audit.defineTask("default constructor", function (taskDone) { + var node; + var success = true; + + success = Should("node = new ConstantSourceNode(context)", function () { + node = new ConstantSourceNode(context); + }).notThrow(); + success = Should("node instanceOf ConstantSourceNode", node instanceof ConstantSourceNode) + .beEqualTo(true) && success; + success = Should("node.offset.value", node.offset.value) + .beEqualTo(1) && success; + + success = Should("node.channelCount", node.channelCount) + .beEqualTo(2) && success; + success = Should("node.channelCountMode", node.channelCountMode) + .beEqualTo("max") && success; + success = Should("node.channelInterpretation", node.channelInterpretation) + .beEqualTo("speakers") && success; + + success = Should("*** new AnalyserNode(context)", success) + .summarize( + "constructed node with correct attributes", + "did not construct correct node correctly") + + taskDone(); + }); + + audit.runTasks(); + </script> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index ce591860..107b4ec 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -865,6 +865,14 @@ method terminate setter onerror setter onmessage +interface ConstantSourceNode : AudioSourceNode + attribute @@toStringTag + getter offset + getter onended + method constructor + method start + method stop + setter onended interface ConvolverNode : AudioNode attribute @@toStringTag getter buffer
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn index 2eb90f313..99d88dbc 100644 --- a/third_party/WebKit/Source/core/BUILD.gn +++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -1035,6 +1035,7 @@ "dom/DocumentStatisticsCollectorTest.cpp", "dom/DocumentTest.cpp", "dom/ElementTest.cpp", + "dom/ElementVisibilityObserverTest.cpp", "dom/ExecutionContextTaskTest.cpp", "dom/MainThreadTaskRunnerTest.cpp", "dom/NodeTest.cpp",
diff --git a/third_party/WebKit/Source/core/dom/ElementVisibilityObserver.cpp b/third_party/WebKit/Source/core/dom/ElementVisibilityObserver.cpp index bc8968562..06769a4 100644 --- a/third_party/WebKit/Source/core/dom/ElementVisibilityObserver.cpp +++ b/third_party/WebKit/Source/core/dom/ElementVisibilityObserver.cpp
@@ -13,8 +13,9 @@ namespace { -bool isInRemoteFrame(Element* element) { - Frame* mainFrame = element->document().frame()->tree().top(); +bool isInRemoteFrame(const Document& document) { + DCHECK(document.frame()); + Frame* mainFrame = document.frame()->tree().top(); return !mainFrame || mainFrame->isRemoteFrame(); } @@ -28,9 +29,13 @@ ElementVisibilityObserver::~ElementVisibilityObserver() = default; void ElementVisibilityObserver::start() { + ExecutionContext* context = m_element->getExecutionContext(); + DCHECK(context->isDocument()); + Document& document = toDocument(*context); + // TODO(zqzhang): IntersectionObserver does not work for RemoteFrame. // Remove this early return when it's fixed. See https://crbug.com/615156 - if (isInRemoteFrame(m_element)) { + if (isInRemoteFrame(document)) { m_element.release(); return; } @@ -38,9 +43,8 @@ DCHECK(!m_intersectionObserver); m_intersectionObserver = IntersectionObserver::create( Vector<Length>(), Vector<float>({std::numeric_limits<float>::min()}), - &m_element->document(), - WTF::bind(&ElementVisibilityObserver::onVisibilityChanged, - wrapWeakPersistent(this))); + &document, WTF::bind(&ElementVisibilityObserver::onVisibilityChanged, + wrapWeakPersistent(this))); DCHECK(m_intersectionObserver); m_intersectionObserver->observe(m_element.release()); }
diff --git a/third_party/WebKit/Source/core/dom/ElementVisibilityObserver.h b/third_party/WebKit/Source/core/dom/ElementVisibilityObserver.h index 89c9f0fc..f42213c 100644 --- a/third_party/WebKit/Source/core/dom/ElementVisibilityObserver.h +++ b/third_party/WebKit/Source/core/dom/ElementVisibilityObserver.h
@@ -5,6 +5,7 @@ #ifndef ElementVisibilityObserver_h #define ElementVisibilityObserver_h +#include "core/CoreExport.h" #include "core/dom/IntersectionObserver.h" #include "platform/heap/Heap.h" #include "platform/heap/Member.h" @@ -22,7 +23,7 @@ // The ElementVisibilityObserver is implemented on top of IntersectionObserver. // It is a layer meant to simplify the usage for C++ Blink code checking for the // visibility of an element. -class ElementVisibilityObserver final +class CORE_EXPORT ElementVisibilityObserver final : public GarbageCollectedFinalized<ElementVisibilityObserver> { WTF_MAKE_NONCOPYABLE(ElementVisibilityObserver);
diff --git a/third_party/WebKit/Source/core/dom/ElementVisibilityObserverTest.cpp b/third_party/WebKit/Source/core/dom/ElementVisibilityObserverTest.cpp new file mode 100644 index 0000000..2645259 --- /dev/null +++ b/third_party/WebKit/Source/core/dom/ElementVisibilityObserverTest.cpp
@@ -0,0 +1,40 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/dom/ElementVisibilityObserver.h" + +#include "core/dom/DOMImplementation.h" +#include "core/dom/Document.h" +#include "core/html/HTMLDivElement.h" +#include "core/html/HTMLDocument.h" +#include "core/testing/DummyPageHolder.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace blink { + +namespace { + +class ElementVisibilityObserverTest : public ::testing::Test { + protected: + void SetUp() override { m_dummyPageHolder = DummyPageHolder::create(); } + + Document& document() { return m_dummyPageHolder->document(); } + + private: + std::unique_ptr<DummyPageHolder> m_dummyPageHolder; +}; + +TEST_F(ElementVisibilityObserverTest, ObserveElementWithoutDocumentFrame) { + HTMLElement* element = HTMLDivElement::create( + *DOMImplementation::create(document())->createHTMLDocument("test")); + ElementVisibilityObserver* observer = + new ElementVisibilityObserver(element, nullptr); + observer->start(); + observer->stop(); + // It should not crash. +} + +} // anonymous namespace + +} // blink namespace
diff --git a/third_party/WebKit/Source/core/frame/Deprecation.cpp b/third_party/WebKit/Source/core/frame/Deprecation.cpp index 4c0d973..86b92fb 100644 --- a/third_party/WebKit/Source/core/frame/Deprecation.cpp +++ b/third_party/WebKit/Source/core/frame/Deprecation.cpp
@@ -462,8 +462,10 @@ return replacedBy("VRDisplay.getPose()", "VRDisplay.getFrameData()"); case UseCounter::DeprecatedBluetoothDeviceUUIDsAttribute: - return "BluetoothDevice.uuids is deprecated. Use getPrimaryServices() to " - "retrieve all available UUIDs."; + return String::format( + "BluetoothDevice.uuids is deprecated and will be removed in %s. Use " + "getPrimaryServices() to retrieve all available UUIDs.", + milestoneString(M57)); // Features that aren't deprecated don't have a deprecation message. default:
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h index 0f496a1..e038370 100644 --- a/third_party/WebKit/Source/core/frame/UseCounter.h +++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -1369,6 +1369,8 @@ V8RTCPeerConnection_UpdateIce_Method = 1647, RTCPeerConnectionCreateDataChannelMaxRetransmitTime = 1648, RTCPeerConnectionCreateDataChannelMaxRetransmits = 1649, + AudioContextCreateConstantSource = 1650, + WebAudioConstantSourceNode = 1651, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json index e8f88d9b..4f46068 100644 --- a/third_party/WebKit/Source/core/inspector/browser_protocol.json +++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -1027,7 +1027,7 @@ "description": "Security details about a request.", "properties": [ { "name": "protocol", "type": "string", "description": "Protocol name (e.g. \"TLS 1.2\" or \"QUIC\")." }, - { "name": "keyExchange", "type": "string", "description": "Key Exchange used by the connection." }, + { "name": "keyExchange", "type": "string", "description": "Key Exchange used by the connection, or the empty string if not applicable." }, { "name": "keyExchangeGroup", "type": "string", "optional": true, "description": "(EC)DH group used by the connection, if applicable." }, { "name": "cipher", "type": "string", "description": "Cipher name." }, { "name": "mac", "type": "string", "optional": true, "description": "TLS MAC. Note that AEAD ciphers do not have separate MACs." },
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp index 6c86ce9..4efa030 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -5502,6 +5502,14 @@ pageBoundaryRule); } +bool LayoutBox::crossesPageBoundary(LayoutUnit offset, + LayoutUnit logicalHeight) const { + if (!view()->layoutState()->pageLogicalHeight()) + return false; + return pageRemainingLogicalHeightForOffset(offset, AssociateWithLatterPage) < + logicalHeight; +} + LayoutUnit LayoutBox::calculatePaginationStrutToFitContent( LayoutUnit offset, LayoutUnit strutToNextPage,
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.h b/third_party/WebKit/Source/core/layout/LayoutBox.h index 5aef1c6a..42c0477 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBox.h +++ b/third_party/WebKit/Source/core/layout/LayoutBox.h
@@ -781,6 +781,7 @@ LayoutUnit pageLogicalHeightForOffset(LayoutUnit) const; LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit, PageBoundaryRule) const; + bool crossesPageBoundary(LayoutUnit offset, LayoutUnit logicalHeight) const; // Calculate the strut to insert in order fit content of size // |contentLogicalHeight|. |strutToNextPage| is the strut to add to |offset|
diff --git a/third_party/WebKit/Source/core/layout/LayoutFieldset.cpp b/third_party/WebKit/Source/core/layout/LayoutFieldset.cpp index 5d94102..cf1f188 100644 --- a/third_party/WebKit/Source/core/layout/LayoutFieldset.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutFieldset.cpp
@@ -174,27 +174,29 @@ LayoutUnit legendLogicalTop; LayoutUnit collapsedLegendExtent; LayoutUnit innerBlockPadding; - // FIXME: We need to account for the legend's margin before too. - if (fieldsetBorderBefore > legendLogicalHeight) { - // The <legend> is smaller than the associated fieldset before border - // so the latter determines positioning of the <legend>. The sizing - // depends on the legend's margins as we want to still follow the - // author's cues. - // Firefox completely ignores the margins in this case which seems wrong. + + if (legendLogicalHeight < fieldsetBorderBefore) { + // Center legend in fieldset border legendLogicalTop = (fieldsetBorderBefore - legendLogicalHeight) / 2; - collapsedLegendExtent = max<LayoutUnit>( - fieldsetBorderBefore, legendLogicalTop + legendLogicalHeight + - marginAfterForChild(*legend)); - innerBlockPadding = marginAfterForChild(*legend) - ? marginAfterForChild(*legend) - legendLogicalTop - : LayoutUnit(); - } else { - collapsedLegendExtent = - legendLogicalHeight + marginAfterForChild(*legend); - innerBlockPadding = - legendLogicalHeight - borderAfter() + marginAfterForChild(*legend); } + // Calculate how much legend + bottom margin sticks below the fieldset + // border + innerBlockPadding = (legendLogicalTop + legendLogicalHeight + + marginAfterForChild(*legend) - fieldsetBorderBefore) + .clampNegativeToZero(); + + if (legendLogicalTop < marginBeforeForChild(*legend)) { + // legend margin pushes everything down + innerBlockPadding += marginBeforeForChild(*legend) - legendLogicalTop; + legendLogicalTop = marginBeforeForChild(*legend); + } + + collapsedLegendExtent = + std::max(fieldsetBorderBefore, marginBeforeForChild(*legend) + + legendLogicalHeight + + marginAfterForChild(*legend)); + if (m_innerBlock) setInnerBlockPadding(isHorizontalWritingMode(), m_innerBlock, innerBlockPadding);
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp b/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp index 920900b..055f399 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp
@@ -206,6 +206,7 @@ } void LayoutTableCell::computeIntrinsicPadding(int rowHeight, + EVerticalAlign verticalAlign, SubtreeLayoutScope& layouter) { int oldIntrinsicPaddingBefore = intrinsicPaddingBefore(); int oldIntrinsicPaddingAfter = intrinsicPaddingAfter(); @@ -214,7 +215,7 @@ oldIntrinsicPaddingAfter; int intrinsicPaddingBefore = 0; - switch (style()->verticalAlign()) { + switch (verticalAlign) { case VerticalAlignSub: case VerticalAlignSuper: case VerticalAlignTextTop:
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableCell.h b/third_party/WebKit/Source/core/layout/LayoutTableCell.h index 963a5aa..57f1089 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTableCell.h +++ b/third_party/WebKit/Source/core/layout/LayoutTableCell.h
@@ -200,7 +200,13 @@ va == VerticalAlignSub || va == VerticalAlignLength; } - void computeIntrinsicPadding(int rowHeight, SubtreeLayoutScope&); + // Align the cell in the block direction. This is done by calculating an + // intrinsic padding before and after the cell contents, so that all cells in + // the row get the same logical height. + void computeIntrinsicPadding(int rowHeight, + EVerticalAlign, + SubtreeLayoutScope&); + void clearIntrinsicPadding() { setIntrinsicPadding(0, 0); } int intrinsicPaddingBefore() const { return m_intrinsicPaddingBefore; }
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp index 7fffc13..f8802d1 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
@@ -1175,7 +1175,19 @@ relayoutCellIfFlexed(*cell, r, rHeight); SubtreeLayoutScope layouter(*cell); - cell->computeIntrinsicPadding(rHeight, layouter); + LayoutUnit rowLogicalTop(m_rowPos[rowIndex]); + EVerticalAlign cellVerticalAlign; + // If the cell crosses a fragmentainer boundary, just align it at the + // top. That's how it was laid out initially, before we knew the final + // row height, and re-aligning it now could result in the cell being + // fragmented differently, which could change its height and thus violate + // the requested alignment. Give up instead of risking circular + // dependencies and unstable layout. + if (crossesPageBoundary(rowLogicalTop, LayoutUnit(rHeight))) + cellVerticalAlign = VerticalAlignTop; + else + cellVerticalAlign = cell->style()->verticalAlign(); + cell->computeIntrinsicPadding(rHeight, cellVerticalAlign, layouter); LayoutRect oldCellRect = cell->frameRect();
diff --git a/third_party/WebKit/Source/core/layout/LayoutTextControl.cpp b/third_party/WebKit/Source/core/layout/LayoutTextControl.cpp index 122547e..f7f18e7b 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTextControl.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutTextControl.cpp
@@ -202,15 +202,17 @@ // avgCharWidth from the width of a '0'. This only seems to apply to a fixed // number of Mac fonts, but, in order to get similar rendering across platforms, // we do this check for all platforms. -bool LayoutTextControl::hasValidAvgCharWidth(const SimpleFontData* font, +bool LayoutTextControl::hasValidAvgCharWidth(const SimpleFontData* fontData, const AtomicString& family) { // Some fonts match avgCharWidth to CJK full-width characters. // Heuristic check to avoid such fonts. - DCHECK(font); - const FontMetrics& metrics = font->getFontMetrics(); - if (metrics.hasZeroWidth() && - font->avgCharWidth() > metrics.zeroWidth() * 1.7) - return false; + DCHECK(fontData); + if (fontData) { + const FontMetrics& metrics = fontData->getFontMetrics(); + if (metrics.hasZeroWidth() && + fontData->avgCharWidth() > metrics.zeroWidth() * 1.7) + return false; + } static HashSet<AtomicString>* fontFamiliesWithInvalidCharWidthMap = nullptr;
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.cpp b/third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.cpp index 424f5f7..50d328d 100644 --- a/third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.cpp +++ b/third_party/WebKit/Source/core/layout/svg/SVGLayoutSupport.cpp
@@ -115,7 +115,10 @@ if (adjustedRect.isEmpty()) return LayoutRect(); - return enclosingLayoutRect(adjustedRect); + // Use enclosingIntRect because we cannot properly apply subpixel offset of + // the SVGRoot since we don't know the desired subpixel accumulation at this + // point. + return LayoutRect(enclosingIntRect(adjustedRect)); } static const LayoutSVGRoot& computeTransformToSVGRoot(
diff --git a/third_party/WebKit/Source/core/loader/ProgressTracker.cpp b/third_party/WebKit/Source/core/loader/ProgressTracker.cpp index 09815527..69833e77 100644 --- a/third_party/WebKit/Source/core/loader/ProgressTracker.cpp +++ b/third_party/WebKit/Source/core/loader/ProgressTracker.cpp
@@ -172,6 +172,9 @@ } void ProgressTracker::maybeSendProgress() { + if (!m_frame->isLoading()) + return; + m_progressValue = initialProgressValue + 0.1; // +0.1 for committing if (m_finishedParsing) m_progressValue += 0.2;
diff --git a/third_party/WebKit/Source/core/paint/FieldsetPainter.cpp b/third_party/WebKit/Source/core/paint/FieldsetPainter.cpp index f79bfb0..26162b3 100644 --- a/third_party/WebKit/Source/core/paint/FieldsetPainter.cpp +++ b/third_party/WebKit/Source/core/paint/FieldsetPainter.cpp
@@ -31,16 +31,18 @@ // https://bugs.webkit.org/show_bug.cgi?id=47236 if (m_layoutFieldset.style()->isHorizontalWritingMode()) { LayoutUnit yOff = - (legend->location().y() > 0) - ? LayoutUnit() - : (legend->size().height() - m_layoutFieldset.borderTop()) / 2; + (legend->location().y() + + (legend->size().height() - m_layoutFieldset.borderTop()) / 2) + .clampNegativeToZero(); + paintRect.setHeight(paintRect.height() - yOff); paintRect.setY(paintRect.y() + yOff); } else { LayoutUnit xOff = - (legend->location().x() > 0) - ? LayoutUnit() - : (legend->size().width() - m_layoutFieldset.borderLeft()) / 2; + (legend->location().x() + + (legend->size().width() - m_layoutFieldset.borderLeft()) / 2) + .clampNegativeToZero(); + paintRect.setWidth(paintRect.width() - xOff); paintRect.setX(paintRect.x() + xOff); } @@ -111,16 +113,18 @@ // https://bugs.webkit.org/show_bug.cgi?id=47236 if (m_layoutFieldset.style()->isHorizontalWritingMode()) { LayoutUnit yOff = - (legend->location().y() > LayoutUnit()) - ? LayoutUnit() - : (legend->size().height() - m_layoutFieldset.borderTop()) / 2; + (legend->location().y() + + (legend->size().height() - m_layoutFieldset.borderTop()) / 2) + .clampNegativeToZero(); + paintRect.expand(LayoutUnit(), -yOff); paintRect.move(LayoutUnit(), yOff); } else { LayoutUnit xOff = - (legend->location().x() > LayoutUnit()) - ? LayoutUnit() - : (legend->size().width() - m_layoutFieldset.borderLeft()) / 2; + (legend->location().x() + + (legend->size().width() - m_layoutFieldset.borderLeft()) / 2) + .clampNegativeToZero(); + paintRect.expand(-xOff, LayoutUnit()); paintRect.move(xOff, LayoutUnit()); }
diff --git a/third_party/WebKit/Source/core/paint/PaintInvalidator.cpp b/third_party/WebKit/Source/core/paint/PaintInvalidator.cpp index ea53d0f..011a4a1 100644 --- a/third_party/WebKit/Source/core/paint/PaintInvalidator.cpp +++ b/third_party/WebKit/Source/core/paint/PaintInvalidator.cpp
@@ -20,14 +20,6 @@ namespace blink { -// TODO(wangxianzhu): Avoid using function when possible. For example, we can -// avoid it by avoiding unnecessary conversions between LayoutRects and -// FloatRects. -static LayoutRect enclosingLayoutRectIfNotEmpty(const FloatRect& floatRect) { - return floatRect.isEmpty() ? LayoutRect(floatRect) - : enclosingLayoutRect(floatRect); -} - static LayoutRect slowMapToVisualRectInAncestorSpace( const LayoutObject& object, const LayoutBoxModelObject& ancestor, @@ -39,7 +31,7 @@ return result; } - LayoutRect result = enclosingLayoutRectIfNotEmpty(rect); + LayoutRect result(rect); if (object.isLayoutView()) toLayoutView(object).mapToVisualRectInAncestorSpace( &ancestor, result, InputIsInFrameCoordinates, DefaultVisualRectFlags); @@ -80,7 +72,7 @@ if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { // In SPv2, visual rects are in the space of their local transform node. rect.moveBy(FloatPoint(context.treeBuilderContext.current.paintOffset)); - return enclosingLayoutRectIfNotEmpty(rect); + return LayoutRect(rect); } LayoutRect result; @@ -89,7 +81,7 @@ result = slowMapToVisualRectInAncestorSpace( object, *context.paintInvalidationContainer, rect); } else if (object == context.paintInvalidationContainer) { - result = enclosingLayoutRectIfNotEmpty(rect); + result = LayoutRect(rect); } else { rect.moveBy(FloatPoint(context.treeBuilderContext.current.paintOffset)); @@ -104,10 +96,9 @@ containerPaintProperties->contentsProperties(); bool success = false; - result = enclosingLayoutRectIfNotEmpty( - geometryMapper.mapToVisualRectInDestinationSpace( - rect, currentTreeState, - containerContentsProperties.propertyTreeState, success)); + result = LayoutRect(geometryMapper.mapToVisualRectInDestinationSpace( + rect, currentTreeState, containerContentsProperties.propertyTreeState, + success)); DCHECK(success); // Convert the result to the container's contents space.
diff --git a/third_party/WebKit/Source/core/style/GridTrackSize.h b/third_party/WebKit/Source/core/style/GridTrackSize.h index 0063215..abef7b6 100644 --- a/third_party/WebKit/Source/core/style/GridTrackSize.h +++ b/third_party/WebKit/Source/core/style/GridTrackSize.h
@@ -103,7 +103,8 @@ bool operator==(const GridTrackSize& other) const { return m_type == other.m_type && m_minTrackBreadth == other.m_minTrackBreadth && - m_maxTrackBreadth == other.m_maxTrackBreadth; + m_maxTrackBreadth == other.m_maxTrackBreadth && + m_fitContentTrackBreadth == other.m_fitContentTrackBreadth; } void cacheMinMaxTrackBreadthTypes() {
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js index e5cc31f1..988fa17e 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
@@ -679,6 +679,7 @@ this.propertiesTreeOutline.element.classList.add("read-only"); } + this._hoverableSelectorsMode = false; this._markSelectorMatches(); this.onpopulate(); }
diff --git a/third_party/WebKit/Source/devtools/front_end/layer_viewer/PaintProfilerView.js b/third_party/WebKit/Source/devtools/front_end/layer_viewer/PaintProfilerView.js index 8f91afda..3fe38609 100644 --- a/third_party/WebKit/Source/devtools/front_end/layer_viewer/PaintProfilerView.js +++ b/third_party/WebKit/Source/devtools/front_end/layer_viewer/PaintProfilerView.js
@@ -258,18 +258,18 @@ /** * @constructor - * @extends {WebInspector.VBox} + * @extends {WebInspector.ThrottledWidget} */ WebInspector.PaintProfilerCommandLogView = function() { - WebInspector.VBox.call(this); + WebInspector.ThrottledWidget.call(this); this.setMinimumSize(100, 25); this.element.classList.add("overflow-auto"); this._treeOutline = new TreeOutlineInShadow(); this.element.appendChild(this._treeOutline.element); - this._reset(); + this._log = []; } WebInspector.PaintProfilerCommandLogView.prototype = { @@ -299,19 +299,25 @@ */ updateWindow: function(selectionWindow) { - this._treeOutline.removeChildren(); - if (!selectionWindow || !this._log.length) - return; - for (var i = selectionWindow.left; i < selectionWindow.right; ++i) - this._appendLogItem(this._treeOutline, this._log[i]); + this._selectionWindow = selectionWindow; + this.update(); }, - _reset: function() + /** + * @override + * @return {!Promise<*>} + */ + doUpdate: function() { - this._log = []; + this._treeOutline.removeChildren(); + if (!this._selectionWindow || !this._log.length) + return Promise.resolve(); + for (var i = this._selectionWindow.left, right = this._selectionWindow.right; i < right; ++i) + this._appendLogItem(this._treeOutline, this._log[i]); + return Promise.resolve(); }, - __proto__: WebInspector.VBox.prototype + __proto__: WebInspector.ThrottledWidget.prototype }; /**
diff --git a/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js b/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js index b523780..a96834d 100644 --- a/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js
@@ -865,7 +865,8 @@ var table = new WebInspector.SecurityDetailsTable(); connectionSection.appendChild(table.element()); table.addRow("Protocol", originState.securityDetails.protocol); - table.addRow("Key Exchange", originState.securityDetails.keyExchange); + if (originState.securityDetails.keyExchange) + table.addRow("Key Exchange", originState.securityDetails.keyExchange); if (originState.securityDetails.keyExchangeGroup) table.addRow("Key Exchange Group", originState.securityDetails.keyExchangeGroup); table.addRow("Cipher", originState.securityDetails.cipher + (originState.securityDetails.mac ? " with " + originState.securityDetails.mac : "")); @@ -968,7 +969,7 @@ sanDiv.classList.add("empty-san"); } else { var truncatedNumToShow = 2; - var listIsTruncated = sanList.length > truncatedNumToShow; + var listIsTruncated = sanList.length > truncatedNumToShow + 1; for (var i = 0; i < sanList.length; i++) { var span = sanDiv.createChild("span", "san-entry"); span.textContent = sanList[i];
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/ThrottledWidget.js b/third_party/WebKit/Source/devtools/front_end/ui/ThrottledWidget.js index e545cf8..0c752306 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/ThrottledWidget.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/ThrottledWidget.js
@@ -17,7 +17,7 @@ WebInspector.ThrottledWidget.prototype = { /** * @protected - * @return {!Promise.<?>} + * @return {!Promise<?>} */ doUpdate: function() { @@ -33,16 +33,14 @@ /** * @this {WebInspector.ThrottledWidget} - * @return {!Promise.<?>} + * @return {!Promise<?>} */ function innerUpdate() { - if (this.isShowing()) { + if (this.isShowing()) return this.doUpdate(); - } else { - this._updateWhenVisible = true; - return Promise.resolve(); - } + this._updateWhenVisible = true; + return Promise.resolve(); } },
diff --git a/third_party/WebKit/Source/devtools/front_end/workspace/IsolatedFileSystemManager.js b/third_party/WebKit/Source/devtools/front_end/workspace/IsolatedFileSystemManager.js index a321293..ee17a3a 100644 --- a/third_party/WebKit/Source/devtools/front_end/workspace/IsolatedFileSystemManager.js +++ b/third_party/WebKit/Source/devtools/front_end/workspace/IsolatedFileSystemManager.js
@@ -226,6 +226,8 @@ _initExcludePatterSetting: function() { var defaultCommonExcludedFolders = [ + "/node_modules/", + "/bower_components/", "/\\.devtools", "/\\.git/", "/\\.sass-cache/",
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaConstraintsImpl.cpp b/third_party/WebKit/Source/modules/mediastream/MediaConstraintsImpl.cpp index 9c997db..b0be707 100644 --- a/third_party/WebKit/Source/modules/mediastream/MediaConstraintsImpl.cpp +++ b/third_party/WebKit/Source/modules/mediastream/MediaConstraintsImpl.cpp
@@ -85,6 +85,7 @@ // TODO(hta): googHotword should go away. https://crbug.com/577627 // From content/renderer/media/media_stream_audio_processor_options.cc const char kEchoCancellation[] = "echoCancellation"; +const char kDisableLocalEcho[] = "disableLocalEcho"; const char kGoogEchoCancellation[] = "googEchoCancellation"; const char kGoogExperimentalEchoCancellation[] = "googEchoCancellation2"; const char kGoogAutoGainControl[] = "googAutoGainControl"; @@ -298,6 +299,10 @@ // represented as an enum, and cause type errors. // https://crbug.com/576582 result.mediaStreamSource.setExact(constraint.m_value); + } else if (constraint.m_name.equals(kDisableLocalEcho) && + RuntimeEnabledFeatures:: + desktopCaptureDisableLocalEchoControlEnabled()) { + result.disableLocalEcho.setExact(toBoolean(constraint.m_value)); } else if (constraint.m_name.equals(kMediaStreamSourceId) || constraint.m_name.equals(kMediaStreamSourceInfoId)) { result.deviceId.setExact(constraint.m_value);
diff --git a/third_party/WebKit/Source/modules/modules_idl_files.gni b/third_party/WebKit/Source/modules/modules_idl_files.gni index 625cb2b..3813b35 100644 --- a/third_party/WebKit/Source/modules/modules_idl_files.gni +++ b/third_party/WebKit/Source/modules/modules_idl_files.gni
@@ -278,6 +278,7 @@ "webaudio/BiquadFilterNode.idl", "webaudio/ChannelMergerNode.idl", "webaudio/ChannelSplitterNode.idl", + "webaudio/ConstantSourceNode.idl", "webaudio/ConvolverNode.idl", "webaudio/DelayNode.idl", "webaudio/DynamicsCompressorNode.idl", @@ -482,6 +483,7 @@ "webaudio/BiquadFilterOptions.idl", "webaudio/ChannelMergerOptions.idl", "webaudio/ChannelSplitterOptions.idl", + "webaudio/ConstantSourceOptions.idl", "webaudio/ConvolverOptions.idl", "webaudio/DelayOptions.idl", "webaudio/DynamicsCompressorOptions.idl", @@ -839,6 +841,8 @@ "$blink_modules_output_dir/webaudio/ChannelMergerOptions.h", "$blink_modules_output_dir/webaudio/ChannelSplitterOptions.cpp", "$blink_modules_output_dir/webaudio/ChannelSplitterOptions.h", + "$blink_modules_output_dir/webaudio/ConstantSourceOptions.cpp", + "$blink_modules_output_dir/webaudio/ConstantSourceOptions.h", "$blink_modules_output_dir/webaudio/ConvolverOptions.cpp", "$blink_modules_output_dir/webaudio/ConvolverOptions.h", "$blink_modules_output_dir/webaudio/DelayOptions.cpp",
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp b/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp index fb01a7b..ec17e259 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp +++ b/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
@@ -223,8 +223,8 @@ } } -void validateShippingOptions(const HeapVector<PaymentShippingOption>& options, - ExceptionState& exceptionState) { +void validateAndFixupShippingOptions(HeapVector<PaymentShippingOption>& options, + ExceptionState& exceptionState) { HashSet<String> uniqueIds; for (const auto& option : options) { if (!option.hasId() || option.id().isEmpty()) { @@ -233,8 +233,7 @@ } if (uniqueIds.contains(option.id())) { - exceptionState.throwTypeError( - "Duplicate shipping option identifiers are not allowed"); + options = HeapVector<PaymentShippingOption>(); return; } uniqueIds.add(option.id()); @@ -291,8 +290,8 @@ } } -void validatePaymentDetails(const PaymentDetails& details, - ExceptionState& exceptionState) { +void validateAndFixupPaymentDetails(PaymentDetails& details, + ExceptionState& exceptionState) { if (!details.hasTotal()) { exceptionState.throwTypeError("Must specify total"); return; @@ -314,7 +313,10 @@ } if (details.hasShippingOptions()) { - validateShippingOptions(details.shippingOptions(), exceptionState); + HeapVector<PaymentShippingOption> fixedShippingOptions = + details.shippingOptions(); + validateAndFixupShippingOptions(fixedShippingOptions, exceptionState); + details.setShippingOptions(fixedShippingOptions); if (exceptionState.hadException()) return; } @@ -524,7 +526,7 @@ return; } - validatePaymentDetails(details, exceptionState); + validateAndFixupPaymentDetails(details, exceptionState); if (exceptionState.hadException()) { m_showResolver->reject( DOMException::create(SyntaxError, exceptionState.message())); @@ -589,17 +591,18 @@ return; } - validatePaymentDetails(details, exceptionState); + PaymentDetails fixedDetails(details); + validateAndFixupPaymentDetails(fixedDetails, exceptionState); if (exceptionState.hadException()) return; - if (details.hasError() && !details.error().isEmpty()) { + if (fixedDetails.hasError() && !fixedDetails.error().isEmpty()) { exceptionState.throwTypeError("Error value should be empty"); return; } if (m_options.requestShipping()) { - m_shippingOption = getSelectedShippingOption(details); + m_shippingOption = getSelectedShippingOption(fixedDetails); m_shippingType = getValidShippingType(m_options.shippingType()); } @@ -612,7 +615,7 @@ m_clientBinding.CreateInterfacePtrAndBind(), mojo::WTFArray<mojom::blink::PaymentMethodDataPtr>::From( validatedMethodData), - mojom::blink::PaymentDetails::From(details), + mojom::blink::PaymentDetails::From(fixedDetails), mojom::blink::PaymentOptions::From(m_options)); }
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequestTest.cpp b/third_party/WebKit/Source/modules/payments/PaymentRequestTest.cpp index 78bb515d..6b964ad 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentRequestTest.cpp +++ b/third_party/WebKit/Source/modules/payments/PaymentRequestTest.cpp
@@ -598,5 +598,46 @@ EXPECT_FALSE(scope.getExceptionState().hadException()); } +TEST(PaymentRequestTest, + ShouldResolveWithEmptyShippingOptionsIfIDsOfShippingOptionsAreDuplicated) { + V8TestingScope scope; + PaymentRequestMockFunctionScope funcs(scope.getScriptState()); + makePaymentRequestOriginSecure(scope.document()); + PaymentDetails details; + details.setTotal(buildPaymentItemForTest()); + HeapVector<PaymentShippingOption> shippingOptions(2); + shippingOptions[0] = buildShippingOptionForTest( + PaymentTestDataId, PaymentTestOverwriteValue, "standard"); + shippingOptions[0].setSelected(true); + shippingOptions[1] = buildShippingOptionForTest( + PaymentTestDataId, PaymentTestOverwriteValue, "standard"); + details.setShippingOptions(shippingOptions); + PaymentOptions options; + options.setRequestShipping(true); + PaymentRequest* request = PaymentRequest::create( + scope.getScriptState(), buildPaymentMethodDataForTest(), details, options, + scope.getExceptionState()); + EXPECT_FALSE(scope.getExceptionState().hadException()); + EXPECT_TRUE(request->shippingOption().isNull()); + request->show(scope.getScriptState()) + .then(funcs.expectNoCall(), funcs.expectNoCall()); + String detailWithShippingOptions = + "{\"total\": {\"label\": \"Total\", \"amount\": {\"currency\": \"USD\", " + "\"value\": \"5.00\"}}," + "\"shippingOptions\": [{\"id\": \"standardShippingOption\", \"label\": " + "\"Standard shipping\", \"amount\": {\"currency\": \"USD\", \"value\": " + "\"5.00\"}, \"selected\": true}, {\"id\": \"standardShippingOption\", " + "\"label\": \"Standard shipping\", \"amount\": {\"currency\": \"USD\", " + "\"value\": \"5.00\"}, \"selected\": true}]}"; + + request->onUpdatePaymentDetails(ScriptValue::from( + scope.getScriptState(), + fromJSONString(scope.getScriptState(), detailWithShippingOptions, + scope.getExceptionState()))); + + EXPECT_FALSE(scope.getExceptionState().hadException()); + EXPECT_TRUE(request->shippingOption().isNull()); +} + } // namespace } // namespace blink
diff --git a/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp b/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp index 483e98f..64600dd 100644 --- a/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp +++ b/third_party/WebKit/Source/modules/sensor/SensorProxy.cpp
@@ -176,8 +176,9 @@ bool SensorProxy::tryReadFromBuffer() { DCHECK(isInitialized()); - ReadingBuffer* buffer = static_cast<ReadingBuffer*>(m_sharedBuffer.get()); - device::OneWriterSeqLock& seqlock = buffer->seqlock.value(); + const ReadingBuffer* buffer = + static_cast<const ReadingBuffer*>(m_sharedBuffer.get()); + const device::OneWriterSeqLock& seqlock = buffer->seqlock.value(); auto version = seqlock.ReadBegin(); auto reading = buffer->reading; if (seqlock.ReadRetry(version))
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioNode.h b/third_party/WebKit/Source/modules/webaudio/AudioNode.h index a75a5f4..c84f3c8 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioNode.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioNode.h
@@ -95,7 +95,8 @@ NodeTypeDynamicsCompressor = 17, NodeTypeWaveShaper = 18, NodeTypeIIRFilter = 19, - NodeTypeEnd = 20 + NodeTypeConstantSource = 20, + NodeTypeEnd = 21 }; AudioHandler(NodeType, AudioNode&, float sampleRate);
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioParam.cpp b/third_party/WebKit/Source/modules/webaudio/AudioParam.cpp index 58cf51d..32bcebe 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioParam.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioParam.cpp
@@ -135,6 +135,8 @@ return "AudioListener.upY"; case ParamTypeAudioListenerUpZ: return "AudioListener.upZ"; + case ParamTypeConstantSourceValue: + return "ConstantSource.sourceValue"; }; NOTREACHED();
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioParam.h b/third_party/WebKit/Source/modules/webaudio/AudioParam.h index 0a6bddf..f52ed1f 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioParam.h +++ b/third_party/WebKit/Source/modules/webaudio/AudioParam.h
@@ -81,6 +81,7 @@ ParamTypeAudioListenerUpX, ParamTypeAudioListenerUpY, ParamTypeAudioListenerUpZ, + ParamTypeConstantSourceValue, }; // AudioParamHandler is an actual implementation of web-exposed AudioParam
diff --git a/third_party/WebKit/Source/modules/webaudio/BUILD.gn b/third_party/WebKit/Source/modules/webaudio/BUILD.gn index 51379f4f0..d14bc39 100644 --- a/third_party/WebKit/Source/modules/webaudio/BUILD.gn +++ b/third_party/WebKit/Source/modules/webaudio/BUILD.gn
@@ -56,6 +56,8 @@ "ChannelMergerNode.h", "ChannelSplitterNode.cpp", "ChannelSplitterNode.h", + "ConstantSourceNode.cpp", + "ConstantSourceNode.h", "ConvolverNode.cpp", "ConvolverNode.h", "DefaultAudioDestinationNode.cpp",
diff --git a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp index 900ff22..a83ad8a 100644 --- a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp +++ b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp
@@ -50,6 +50,7 @@ #include "modules/webaudio/BiquadFilterNode.h" #include "modules/webaudio/ChannelMergerNode.h" #include "modules/webaudio/ChannelSplitterNode.h" +#include "modules/webaudio/ConstantSourceNode.h" #include "modules/webaudio/ConvolverNode.h" #include "modules/webaudio/DefaultAudioDestinationNode.h" #include "modules/webaudio/DelayNode.h" @@ -328,6 +329,13 @@ return node; } +ConstantSourceNode* BaseAudioContext::createConstantSource( + ExceptionState& exceptionState) { + DCHECK(isMainThread()); + + return ConstantSourceNode::create(*this, exceptionState); +} + MediaElementAudioSourceNode* BaseAudioContext::createMediaElementSource( HTMLMediaElement* mediaElement, ExceptionState& exceptionState) {
diff --git a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h index aa2c5f8b..94474e47 100644 --- a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h +++ b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h
@@ -57,6 +57,7 @@ class BiquadFilterNode; class ChannelMergerNode; class ChannelSplitterNode; +class ConstantSourceNode; class ConvolverNode; class DelayNode; class Dictionary; @@ -169,6 +170,7 @@ // The AudioNode create methods are called on the main thread (from // JavaScript). AudioBufferSourceNode* createBufferSource(ExceptionState&); + ConstantSourceNode* createConstantSource(ExceptionState&); MediaElementAudioSourceNode* createMediaElementSource(HTMLMediaElement*, ExceptionState&); MediaStreamAudioSourceNode* createMediaStreamSource(MediaStream*,
diff --git a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.idl b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.idl index f428634..2ccb6b4 100644 --- a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.idl +++ b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.idl
@@ -36,6 +36,7 @@ // Sources [RaisesException, MeasureAs=AudioContextCreateBufferSource] AudioBufferSourceNode createBufferSource(); + [RaisesException, MeasureAs=AudioContextCreateConstantSource] ConstantSourceNode createConstantSource(); // Processing nodes [RaisesException, MeasureAs=AudioContextCreateGain] GainNode createGain();
diff --git a/third_party/WebKit/Source/modules/webaudio/ConstantSourceNode.cpp b/third_party/WebKit/Source/modules/webaudio/ConstantSourceNode.cpp new file mode 100644 index 0000000..7af4e07 --- /dev/null +++ b/third_party/WebKit/Source/modules/webaudio/ConstantSourceNode.cpp
@@ -0,0 +1,155 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "modules/webaudio/ConstantSourceNode.h" + +#include "bindings/core/v8/ExceptionMessages.h" +#include "bindings/core/v8/ExceptionState.h" +#include "core/dom/ExceptionCode.h" +#include "modules/webaudio/AudioNodeOutput.h" +#include "modules/webaudio/ConstantSourceOptions.h" +#include "platform/audio/AudioUtilities.h" +#include "wtf/MathExtras.h" +#include "wtf/StdLibExtras.h" +#include <algorithm> + +namespace blink { + +ConstantSourceHandler::ConstantSourceHandler(AudioNode& node, + float sampleRate, + AudioParamHandler& offset) + : AudioScheduledSourceHandler(NodeTypeConstantSource, node, sampleRate), + m_offset(offset), + m_sampleAccurateValues(ProcessingSizeInFrames) { + // A ConstantSource is always mono. + addOutput(1); + + initialize(); +} + +PassRefPtr<ConstantSourceHandler> ConstantSourceHandler::create( + AudioNode& node, + float sampleRate, + AudioParamHandler& offset) { + return adoptRef(new ConstantSourceHandler(node, sampleRate, offset)); +} + +ConstantSourceHandler::~ConstantSourceHandler() { + uninitialize(); +} + +void ConstantSourceHandler::process(size_t framesToProcess) { + AudioBus* outputBus = output(0).bus(); + DCHECK(outputBus); + + if (!isInitialized() || !outputBus->numberOfChannels()) { + outputBus->zero(); + return; + } + + // The audio thread can't block on this lock, so we call tryLock() instead. + MutexTryLocker tryLocker(m_processLock); + if (!tryLocker.locked()) { + // Too bad - the tryLock() failed. + outputBus->zero(); + return; + } + + size_t quantumFrameOffset; + size_t nonSilentFramesToProcess; + + // Figure out where in the current rendering quantum that the source is + // active and for how many frames. + updateSchedulingInfo(framesToProcess, outputBus, quantumFrameOffset, + nonSilentFramesToProcess); + + if (!nonSilentFramesToProcess) { + outputBus->zero(); + return; + } + + if (m_offset->hasSampleAccurateValues()) { + DCHECK_LE(framesToProcess, m_sampleAccurateValues.size()); + if (framesToProcess <= m_sampleAccurateValues.size()) { + float* offsets = m_sampleAccurateValues.data(); + m_offset->calculateSampleAccurateValues(offsets, framesToProcess); + if (nonSilentFramesToProcess > 0) { + memcpy(outputBus->channel(0)->mutableData() + quantumFrameOffset, + offsets + quantumFrameOffset, + nonSilentFramesToProcess * sizeof(*offsets)); + outputBus->clearSilentFlag(); + } else { + outputBus->zero(); + } + } + } else { + float value = m_offset->value(); + + if (value == 0) { + outputBus->zero(); + } else { + float* dest = outputBus->channel(0)->mutableData(); + dest += quantumFrameOffset; + for (unsigned k = 0; k < nonSilentFramesToProcess; ++k) { + dest[k] = value; + } + outputBus->clearSilentFlag(); + } + } +} + +bool ConstantSourceHandler::propagatesSilence() const { + return !isPlayingOrScheduled() || hasFinished(); +} + +// ---------------------------------------------------------------- +ConstantSourceNode::ConstantSourceNode(BaseAudioContext& context) + : AudioScheduledSourceNode(context), + m_offset(AudioParam::create(context, ParamTypeConstantSourceValue, 1)) { + setHandler(ConstantSourceHandler::create(*this, context.sampleRate(), + m_offset->handler())); +} + +ConstantSourceNode* ConstantSourceNode::create(BaseAudioContext& context, + ExceptionState& exceptionState) { + DCHECK(isMainThread()); + + if (context.isContextClosed()) { + context.throwExceptionForClosedState(exceptionState); + return nullptr; + } + + return new ConstantSourceNode(context); +} + +ConstantSourceNode* ConstantSourceNode::create( + BaseAudioContext* context, + const ConstantSourceOptions& options, + ExceptionState& exceptionState) { + DCHECK(isMainThread()); + + ConstantSourceNode* node = create(*context, exceptionState); + + if (!node) + return nullptr; + + node->offset()->setValue(options.offset()); + + return node; +} + +DEFINE_TRACE(ConstantSourceNode) { + visitor->trace(m_offset); + AudioScheduledSourceNode::trace(visitor); +} + +ConstantSourceHandler& ConstantSourceNode::constantSourceHandler() const { + return static_cast<ConstantSourceHandler&>(handler()); +} + +AudioParam* ConstantSourceNode::offset() { + return m_offset; +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/modules/webaudio/ConstantSourceNode.h b/third_party/WebKit/Source/modules/webaudio/ConstantSourceNode.h new file mode 100644 index 0000000..e6d1699 --- /dev/null +++ b/third_party/WebKit/Source/modules/webaudio/ConstantSourceNode.h
@@ -0,0 +1,66 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ConstantSourceNode_h +#define ConstantSourceNode_h + +#include "modules/webaudio/AudioParam.h" +#include "modules/webaudio/AudioScheduledSourceNode.h" +#include "platform/audio/AudioBus.h" +#include "wtf/PassRefPtr.h" +#include "wtf/RefPtr.h" +#include "wtf/Threading.h" + +namespace blink { + +class BaseAudioContext; +class ConstantSourceOptions; +class ExceptionState; + +// ConstantSourceNode is an audio generator for a constant source + +class ConstantSourceHandler final : public AudioScheduledSourceHandler { + public: + static PassRefPtr<ConstantSourceHandler> create(AudioNode&, + float sampleRate, + AudioParamHandler& offset); + ~ConstantSourceHandler() override; + + // AudioHandler + void process(size_t framesToProcess) override; + + private: + ConstantSourceHandler(AudioNode&, + float sampleRate, + AudioParamHandler& offset); + + // If we are no longer playing, propogate silence ahead to downstream nodes. + bool propagatesSilence() const override; + + RefPtr<AudioParamHandler> m_offset; + AudioFloatArray m_sampleAccurateValues; +}; + +class ConstantSourceNode final : public AudioScheduledSourceNode { + DEFINE_WRAPPERTYPEINFO(); + + public: + static ConstantSourceNode* create(BaseAudioContext&, ExceptionState&); + static ConstantSourceNode* create(BaseAudioContext*, + const ConstantSourceOptions&, + ExceptionState&); + DECLARE_VIRTUAL_TRACE(); + + AudioParam* offset(); + + private: + ConstantSourceNode(BaseAudioContext&); + ConstantSourceHandler& constantSourceHandler() const; + + Member<AudioParam> m_offset; +}; + +} // namespace blink + +#endif // ConstantSourceNode_h
diff --git a/third_party/WebKit/Source/modules/webaudio/ConstantSourceNode.idl b/third_party/WebKit/Source/modules/webaudio/ConstantSourceNode.idl new file mode 100644 index 0000000..3773817 --- /dev/null +++ b/third_party/WebKit/Source/modules/webaudio/ConstantSourceNode.idl
@@ -0,0 +1,16 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// See https://webaudio.github.io/web-audio-api/#ConstantSourceNode +[ + Constructor(BaseAudioContext context, optional ConstantSourceOptions options), + RaisesException=Constructor, + ActiveScriptWrappable, +] +interface ConstantSourceNode : AudioSourceNode { + readonly attribute AudioParam offset; + [RaisesException] void start(optional double when); + [RaisesException] void stop(optional double when); + attribute EventHandler onended; +};
diff --git a/third_party/WebKit/Source/modules/webaudio/ConstantSourceOptions.idl b/third_party/WebKit/Source/modules/webaudio/ConstantSourceOptions.idl new file mode 100644 index 0000000..5cd584c --- /dev/null +++ b/third_party/WebKit/Source/modules/webaudio/ConstantSourceOptions.idl
@@ -0,0 +1,8 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// See https://webaudio.github.io/web-audio-api/#constantsourceoptions +dictionary ConstantSourceOptions { + float offset = 1; +}; \ No newline at end of file
diff --git a/third_party/WebKit/Source/modules/webaudio/WindowWebAudio.idl b/third_party/WebKit/Source/modules/webaudio/WindowWebAudio.idl index 3b23db3..78f08c12 100644 --- a/third_party/WebKit/Source/modules/webaudio/WindowWebAudio.idl +++ b/third_party/WebKit/Source/modules/webaudio/WindowWebAudio.idl
@@ -17,6 +17,7 @@ [MeasureAs=WebAudioBiquadFilterNode] attribute BiquadFilterNodeConstructor BiquadFilterNode; [MeasureAs=WebAudioChannelMergerNode] attribute ChannelMergerNodeConstructor ChannelMergerNode; [MeasureAs=WebAudioChannelSplitterNode] attribute ChannelSplitterNodeConstructor ChannelSplitterNode; + [MeasureAs=WebAudioConstantSourceNode] attribute ConstantSourceNodeConstructor ConstantSourceNode; [MeasureAs=WebAudioConvolverNode] attribute ConvolverNodeConstructor ConvolverNode; [MeasureAs=WebAudioDelayNode] attribute DelayNodeConstructor DelayNode; [MeasureAs=WebAudioDynamicsCompressorNode] attribute DynamicsCompressorNodeConstructor DynamicsCompressorNode;
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in index 7ddf05b..6e9a343 100644 --- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in +++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in
@@ -79,6 +79,7 @@ CustomSchemeHandler depends_on=NavigatorContentUtils, status=experimental Database status=stable DecodeToYUV status=experimental +DesktopCaptureDisableLocalEchoControl status=experimental DeviceLight status=experimental DisplayList2dCanvas status=stable DocumentWriteEvaluator @@ -258,4 +259,4 @@ WebShare status=experimental, origin_trial_feature_name=WebShare, origin_trial_os=android Worklet status=experimental ParseHTMLOnMainThread status=test -SendBeaconThrowForBlobWithNonSimpleType status=experimental +SendBeaconThrowForBlobWithNonSimpleType status=experimental \ No newline at end of file
diff --git a/third_party/WebKit/Source/platform/exported/WebMediaConstraints.cpp b/third_party/WebKit/Source/platform/exported/WebMediaConstraints.cpp index dfabaa5..2cae78f 100644 --- a/third_party/WebKit/Source/platform/exported/WebMediaConstraints.cpp +++ b/third_party/WebKit/Source/platform/exported/WebMediaConstraints.cpp
@@ -355,6 +355,7 @@ latency("latency"), channelCount("channelCount"), deviceId("deviceId"), + disableLocalEcho("disableLocalEcho"), groupId("groupId"), mediaStreamSource("mediaStreamSource"), renderToAssociatedSink("chromeRenderToAssociatedSink"), @@ -413,6 +414,7 @@ &deviceId, &groupId, &mediaStreamSource, + &disableLocalEcho, &renderToAssociatedSink, &hotwordEnabled, &googEchoCancellation,
diff --git a/third_party/WebKit/Source/platform/graphics/DeferredImageDecoderTest.cpp b/third_party/WebKit/Source/platform/graphics/DeferredImageDecoderTest.cpp index 808445cb..a87875e6 100644 --- a/third_party/WebKit/Source/platform/graphics/DeferredImageDecoderTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/DeferredImageDecoderTest.cpp
@@ -113,9 +113,7 @@ void decoderBeingDestroyed() override { m_actualDecoder = 0; } - void decodeRequested(size_t, SkBitmap::Allocator*) override { - ++m_decodeRequestCount; - } + void decodeRequested() override { ++m_decodeRequestCount; } size_t frameCount() override { return m_frameCount; }
diff --git a/third_party/WebKit/Source/platform/graphics/ImageDecodingStoreTest.cpp b/third_party/WebKit/Source/platform/graphics/ImageDecodingStoreTest.cpp index 0cbff76..00dd6d1 100644 --- a/third_party/WebKit/Source/platform/graphics/ImageDecodingStoreTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/ImageDecodingStoreTest.cpp
@@ -45,7 +45,7 @@ void decoderBeingDestroyed() override { ++m_decodersDestroyed; } - void decodeRequested(size_t, SkBitmap::Allocator*) override { + void decodeRequested() override { // Decoder is never used by ImageDecodingStore. ASSERT_TRUE(false); }
diff --git a/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp b/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp index c68470e..c56bd124 100644 --- a/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp +++ b/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp
@@ -286,8 +286,10 @@ // Try to create an ImageDecoder if we are not given one. ASSERT(decoder); + bool newDecoder = false; bool shouldCallSetData = true; if (!*decoder) { + newDecoder = true; if (m_imageDecoderFactory) *decoder = m_imageDecoderFactory->create().release(); @@ -304,15 +306,15 @@ return false; } - if (shouldCallSetData) - (*decoder)->setData(data, allDataReceived); - if (!(*decoder)->frameHasDependentFrame(index) && allDataReceived) { + if (!m_isMultiFrame && newDecoder && allDataReceived) { // If we're using an external memory allocator that means we're decoding // directly into the output memory and we can save one memcpy. ASSERT(allocator); - (*decoder)->setFrameMemoryAllocator(index, allocator); + (*decoder)->setMemoryAllocator(allocator); } + if (shouldCallSetData) + (*decoder)->setData(data, allDataReceived); ImageFrame* frame = (*decoder)->frameBufferAtIndex(index); // For multi-frame image decoders, we need to know how many frames are @@ -325,7 +327,7 @@ (*decoder)->setData(PassRefPtr<SegmentReader>(nullptr), false); // Unref SegmentReader from ImageDecoder. (*decoder)->clearCacheExceptFrame(index); - (*decoder)->setFrameMemoryAllocator(index, 0); + (*decoder)->setMemoryAllocator(0); if (!frame || frame->getStatus() == ImageFrame::FrameEmpty) return false;
diff --git a/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp b/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp index d8a9a1f8..99ff1750 100644 --- a/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp
@@ -65,8 +65,6 @@ useMockImageDecoderFactory(); m_decodersDestroyed = 0; m_decodeRequestCount = 0; - m_decodeRequestedForFrameIndex = kNotFound; - m_decodeRequestedWithFrameAllocator = nullptr; m_status = ImageFrame::FrameEmpty; m_frameCount = 1; m_requestedClearExceptFrame = kNotFound; @@ -76,11 +74,7 @@ void decoderBeingDestroyed() override { ++m_decodersDestroyed; } - void decodeRequested(size_t index, SkBitmap::Allocator* allocator) override { - ++m_decodeRequestCount; - m_decodeRequestedForFrameIndex = index; - m_decodeRequestedWithFrameAllocator = allocator; - } + void decodeRequested() override { ++m_decodeRequestCount; } ImageFrame::Status status() override { ImageFrame::Status currentStatus = m_status; @@ -98,10 +92,6 @@ } float frameDuration() const override { return 0; } - size_t getRequiredPreviousFrameIndex(size_t frameIndex) const override { - return (frameIndex == 1) ? 0 : kNotFound; - } - protected: void useMockImageDecoderFactory() { m_generator->setImageDecoderFactory( @@ -130,8 +120,6 @@ RefPtr<ImageFrameGenerator> m_generator; int m_decodersDestroyed; int m_decodeRequestCount; - size_t m_decodeRequestedForFrameIndex; - SkBitmap::Allocator* m_decodeRequestedWithFrameAllocator; ImageFrame::Status m_status; ImageFrame::Status m_nextFrameStatus; size_t m_frameCount; @@ -247,9 +235,6 @@ m_generator->decodeAndScale(m_segmentReader.get(), true, 0, imageInfo(), buffer, 100 * 4); EXPECT_EQ(1, m_decodeRequestCount); - EXPECT_EQ(0u, m_decodeRequestedForFrameIndex); - // Frame 0 is not decoded directly to |buffer| since frame 1 depends on it. - EXPECT_EQ(nullptr, m_decodeRequestedWithFrameAllocator); EXPECT_EQ(0, m_decodersDestroyed); EXPECT_EQ(0U, m_requestedClearExceptFrame); @@ -258,10 +243,6 @@ m_generator->decodeAndScale(m_segmentReader.get(), true, 1, imageInfo(), buffer, 100 * 4); EXPECT_EQ(2, m_decodeRequestCount); - EXPECT_EQ(1u, m_decodeRequestedForFrameIndex); - // Non-null allocator means that frame 1 is decoded directly to |buffer|. - // This is because no other frame requires frame 1 data for decoding. - EXPECT_NE(nullptr, m_decodeRequestedWithFrameAllocator); EXPECT_EQ(0, m_decodersDestroyed); EXPECT_EQ(1U, m_requestedClearExceptFrame); @@ -273,8 +254,6 @@ m_generator->decodeAndScale(m_segmentReader.get(), true, 2, imageInfo(), buffer, 100 * 4); EXPECT_EQ(3, m_decodeRequestCount); - EXPECT_EQ(2u, m_decodeRequestedForFrameIndex); - EXPECT_NE(nullptr, m_decodeRequestedWithFrameAllocator); EXPECT_EQ(0, m_decodersDestroyed); EXPECT_EQ(kNotFound, m_requestedClearExceptFrame); }
diff --git a/third_party/WebKit/Source/platform/graphics/PictureSnapshot.cpp b/third_party/WebKit/Source/platform/graphics/PictureSnapshot.cpp index 74182651..817f38f1 100644 --- a/third_party/WebKit/Source/platform/graphics/PictureSnapshot.cpp +++ b/third_party/WebKit/Source/platform/graphics/PictureSnapshot.cpp
@@ -121,12 +121,13 @@ unsigned toStep, double scale) const { const SkIRect bounds = m_picture->cullRect().roundOut(); + int width = ceil(scale * bounds.width()); + int height = ceil(scale * bounds.height()); // TODO(fmalita): convert this to SkSurface/SkImage, drop the intermediate // SkBitmap. SkBitmap bitmap; - bitmap.allocPixels( - SkImageInfo::MakeN32Premul(bounds.width(), bounds.height())); + bitmap.allocPixels(SkImageInfo::MakeN32Premul(width, height)); bitmap.eraseARGB(0, 0, 0, 0); { ReplayingCanvas canvas(bitmap, fromStep, toStep);
diff --git a/third_party/WebKit/Source/platform/graphics/test/MockImageDecoder.h b/third_party/WebKit/Source/platform/graphics/test/MockImageDecoder.h index 03a5b54c..c305881 100644 --- a/third_party/WebKit/Source/platform/graphics/test/MockImageDecoder.h +++ b/third_party/WebKit/Source/platform/graphics/test/MockImageDecoder.h
@@ -36,7 +36,7 @@ MockImageDecoderClient() : m_firstFrameForcedToBeEmpty(false) {} virtual void decoderBeingDestroyed() = 0; - virtual void decodeRequested(size_t, SkBitmap::Allocator*) = 0; + virtual void decodeRequested() = 0; virtual ImageFrame::Status status() = 0; virtual size_t frameCount() = 0; virtual int repetitionCount() const = 0; @@ -50,11 +50,6 @@ // MockImageDecoder::decodedSize() below. virtual IntSize decodedSize() const { return IntSize(); } - // Clients can control frame dependency by overriding this method. - virtual size_t getRequiredPreviousFrameIndex(size_t) const { - return kNotFound; - } - void forceFirstFrameToBeEmpty() { m_firstFrameForcedToBeEmpty = true; }; bool firstFrameForcedToBeEmpty() const { return m_firstFrameForcedToBeEmpty; } @@ -111,7 +106,7 @@ size_t decodeFrameCount() override { return m_client->frameCount(); } void decode(size_t index) override { - m_client->decodeRequested(index, m_frameBufferCache[index].allocator()); + m_client->decodeRequested(); m_frameBufferCache[index].setStatus(m_client->status()); } @@ -119,8 +114,6 @@ m_frameBufferCache[index].setSizeAndColorProfile( size().width(), size().height(), colorProfile()); m_frameBufferCache[index].setHasAlpha(false); - m_frameBufferCache[index].setRequiredPreviousFrameIndex( - m_client->getRequiredPreviousFrameIndex(index)); } MockImageDecoderClient* m_client;
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp index 1000be7f2..9f3aeab 100644 --- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp +++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp
@@ -230,25 +230,6 @@ return frameBytesCleared; } -void ImageDecoder::setFrameMemoryAllocator(size_t frameIndex, - SkBitmap::Allocator* allocator) { - if (frameIndex <= m_frameBufferCache.size()) - m_frameBufferCache[frameIndex].setMemoryAllocator(allocator); -} - -bool ImageDecoder::frameHasDependentFrame(size_t frameIndex) { - if ((frameIndex + 1) >= frameCount()) - return false; - size_t nextFrameRequiredFrameIndex = - m_frameBufferCache[frameIndex + 1].requiredPreviousFrameIndex(); - DCHECK(nextFrameRequiredFrameIndex == kNotFound || - nextFrameRequiredFrameIndex == frameIndex || - (nextFrameRequiredFrameIndex < frameIndex && - m_frameBufferCache[frameIndex].getDisposalMethod() == - ImageFrame::DisposeOverwritePrevious)); - return (nextFrameRequiredFrameIndex == frameIndex); -} - void ImageDecoder::clearFrameBuffer(size_t frameIndex) { m_frameBufferCache[frameIndex].clearPixelData(); }
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h index 3ed45cd..ced7fa20 100644 --- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h +++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h
@@ -258,18 +258,20 @@ // and returns true. Otherwise returns false. virtual bool hotSpot(IntPoint&) const { return false; } + virtual void setMemoryAllocator(SkBitmap::Allocator* allocator) { + // FIXME: this doesn't work for images with multiple frames. + if (m_frameBufferCache.isEmpty()) { + m_frameBufferCache.resize(1); + m_frameBufferCache[0].setRequiredPreviousFrameIndex( + findRequiredPreviousFrame(0, false)); + } + m_frameBufferCache[0].setMemoryAllocator(allocator); + } + virtual bool canDecodeToYUV() { return false; } virtual bool decodeToYUV() { return false; } virtual void setImagePlanes(std::unique_ptr<ImagePlanes>) {} - // If the frame has not been allocated, enables allocation on the memory - // provided by client. - void setFrameMemoryAllocator(size_t, SkBitmap::Allocator*); - - // Parses the data and returns whether any later frames depend on the image - // data of the provided frame. - bool frameHasDependentFrame(size_t); - protected: ImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOption colorOptions,
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTest.cpp b/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTest.cpp index bd41a06..16af027 100644 --- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTest.cpp +++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTest.cpp
@@ -66,7 +66,6 @@ private: void decodeSize() override {} - size_t decodeFrameCount() override { return m_frameBufferCache.size(); } void decode(size_t index) override {} }; @@ -94,20 +93,14 @@ // The first frame doesn't require any previous frame. EXPECT_EQ(kNotFound, frameBuffers[0].requiredPreviousFrameIndex()); - EXPECT_TRUE(decoder->frameHasDependentFrame(0)); // The previous DisposeNotSpecified frame is required. EXPECT_EQ(0u, frameBuffers[1].requiredPreviousFrameIndex()); // DisposeKeep is treated as DisposeNotSpecified. EXPECT_EQ(1u, frameBuffers[2].requiredPreviousFrameIndex()); - EXPECT_TRUE(decoder->frameHasDependentFrame(1)); // Previous DisposeOverwritePrevious frames are skipped. EXPECT_EQ(1u, frameBuffers[3].requiredPreviousFrameIndex()); EXPECT_EQ(1u, frameBuffers[4].requiredPreviousFrameIndex()); EXPECT_EQ(4u, frameBuffers[5].requiredPreviousFrameIndex()); - EXPECT_FALSE(decoder->frameHasDependentFrame(2)); - EXPECT_FALSE(decoder->frameHasDependentFrame(3)); - EXPECT_TRUE(decoder->frameHasDependentFrame(4)); - EXPECT_FALSE(decoder->frameHasDependentFrame(5)); } TEST(ImageDecoderTest, requiredPreviousFrameIndexDisposeOverwriteBgcolor) {
diff --git a/third_party/WebKit/Source/platform/network/ResourceResponse.h b/third_party/WebKit/Source/platform/network/ResourceResponse.h index 4932461..0daca5d 100644 --- a/third_party/WebKit/Source/platform/network/ResourceResponse.h +++ b/third_party/WebKit/Source/platform/network/ResourceResponse.h
@@ -104,6 +104,8 @@ SecurityDetails() : validFrom(0), validTo(0) {} // All strings are human-readable values. String protocol; + // keyExchange is the empty string if not applicable for the connection's + // protocol. String keyExchange; // keyExchangeGroup is the empty string if not applicable for the // connection's key exchange.
diff --git a/third_party/WebKit/public/platform/WebMediaConstraints.h b/third_party/WebKit/public/platform/WebMediaConstraints.h index 43aa624..a1745907 100644 --- a/third_party/WebKit/public/platform/WebMediaConstraints.h +++ b/third_party/WebKit/public/platform/WebMediaConstraints.h
@@ -229,6 +229,7 @@ DoubleConstraint latency; LongConstraint channelCount; StringConstraint deviceId; + BooleanConstraint disableLocalEcho; StringConstraint groupId; // Constraints not exposed in Blink at the moment, only through // the legacy name interface.
diff --git a/third_party/WebKit/public/platform/WebURLResponse.h b/third_party/WebKit/public/platform/WebURLResponse.h index d0be07f..a78f777 100644 --- a/third_party/WebKit/public/platform/WebURLResponse.h +++ b/third_party/WebKit/public/platform/WebURLResponse.h
@@ -114,6 +114,8 @@ sctList(sctList) {} // All strings are human-readable values. WebString protocol; + // keyExchange is the empty string if not applicable for the connection's + // protocol. WebString keyExchange; // keyExchangeGroup is the empty string if not applicable for the // connection's key exchange.
diff --git a/third_party/boringssl/BUILD.generated.gni b/third_party/boringssl/BUILD.generated.gni index 6fd6c528..27b10e38 100644 --- a/third_party/boringssl/BUILD.generated.gni +++ b/third_party/boringssl/BUILD.generated.gni
@@ -8,6 +8,7 @@ "err_data.c", "src/crypto/aes/aes.c", "src/crypto/aes/internal.h", + "src/crypto/aes/key_wrap.c", "src/crypto/aes/mode_wrappers.c", "src/crypto/asn1/a_bitstr.c", "src/crypto/asn1/a_bool.c", @@ -563,4 +564,5 @@ "read_pem", "server", "spki", + "ssl_ctx_api", ]
diff --git a/third_party/boringssl/BUILD.gn b/third_party/boringssl/BUILD.gn index afe9e0d7..ed3754ce 100644 --- a/third_party/boringssl/BUILD.gn +++ b/third_party/boringssl/BUILD.gn
@@ -203,6 +203,8 @@ libfuzzer_options = [ "max_len=4096" ] } else if ("spki" == fuzzer) { libfuzzer_options = [ "max_len=1024" ] + } else if ("ssl_ctx_api" == fuzzer) { + libfuzzer_options = [ "max_len=256" ] } } }
diff --git a/third_party/boringssl/err_data.c b/third_party/boringssl/err_data.c index c1257cdc..001145d 100644 --- a/third_party/boringssl/err_data.c +++ b/third_party/boringssl/err_data.c
@@ -178,42 +178,42 @@ 0x28340c19, 0x283480ac, 0x283500ea, - 0x2c3228ca, - 0x2c32a8d8, - 0x2c3328ea, - 0x2c33a8fc, - 0x2c342910, - 0x2c34a922, - 0x2c35293d, - 0x2c35a94f, - 0x2c362962, + 0x2c322910, + 0x2c32a91e, + 0x2c332930, + 0x2c33a942, + 0x2c342956, + 0x2c34a968, + 0x2c352983, + 0x2c35a995, + 0x2c3629a8, 0x2c36832d, - 0x2c37296f, - 0x2c37a981, - 0x2c382994, - 0x2c38a9ab, - 0x2c3929b9, - 0x2c39a9c9, - 0x2c3a29db, - 0x2c3aa9ef, - 0x2c3b2a00, - 0x2c3baa1f, - 0x2c3c2a33, - 0x2c3caa49, - 0x2c3d2a62, - 0x2c3daa7f, - 0x2c3e2a90, - 0x2c3eaa9e, - 0x2c3f2ab6, - 0x2c3faace, - 0x2c402adb, + 0x2c3729b5, + 0x2c37a9c7, + 0x2c3829da, + 0x2c38a9f1, + 0x2c3929ff, + 0x2c39aa0f, + 0x2c3a2a21, + 0x2c3aaa35, + 0x2c3b2a46, + 0x2c3baa65, + 0x2c3c2a79, + 0x2c3caa8f, + 0x2c3d2aa8, + 0x2c3daac5, + 0x2c3e2ad6, + 0x2c3eaae4, + 0x2c3f2afc, + 0x2c3fab14, + 0x2c402b21, 0x2c4090e7, - 0x2c412aec, - 0x2c41aaff, + 0x2c412b32, + 0x2c41ab45, 0x2c4210c0, - 0x2c42ab10, + 0x2c42ab56, 0x2c430720, - 0x2c43aa11, + 0x2c43aa57, 0x30320000, 0x30328015, 0x3033001f, @@ -429,74 +429,74 @@ 0x405b1e9e, 0x405b9eaf, 0x405c1ec2, - 0x405c9ed3, - 0x405d1ee0, - 0x405d9ef7, - 0x405e1f17, + 0x405c9ee3, + 0x405d1ef0, + 0x405d9f07, + 0x405e1f27, 0x405e8a95, - 0x405f1f38, - 0x405f9f45, - 0x40601f53, - 0x40609f75, - 0x40611f9d, - 0x40619fb2, - 0x40621fc9, - 0x40629fda, - 0x40631feb, - 0x4063a000, - 0x40642017, - 0x4064a043, - 0x4065205e, - 0x4065a075, - 0x4066208d, - 0x4066a0b7, - 0x406720e2, - 0x4067a103, - 0x40682116, - 0x4068a137, - 0x40692169, - 0x4069a197, - 0x406a21b8, - 0x406aa1d8, - 0x406b2360, - 0x406ba383, - 0x406c2399, - 0x406ca5c5, - 0x406d25f4, - 0x406da61c, - 0x406e264a, - 0x406ea662, - 0x406f2681, - 0x406fa696, - 0x407026a9, - 0x4070a6c6, + 0x405f1f48, + 0x405f9f55, + 0x40601f63, + 0x40609f85, + 0x40611fad, + 0x40619fc2, + 0x40621fd9, + 0x40629fea, + 0x40631ffb, + 0x4063a010, + 0x40642027, + 0x4064a053, + 0x4065206e, + 0x4065a085, + 0x4066209d, + 0x4066a0c7, + 0x406720f2, + 0x4067a113, + 0x40682126, + 0x4068a147, + 0x40692179, + 0x4069a1a7, + 0x406a21c8, + 0x406aa1e8, + 0x406b2370, + 0x406ba393, + 0x406c23a9, + 0x406ca60b, + 0x406d263a, + 0x406da662, + 0x406e2690, + 0x406ea6a8, + 0x406f26c7, + 0x406fa6dc, + 0x407026ef, + 0x4070a70c, 0x40710800, - 0x4071a6d8, - 0x407226eb, - 0x4072a704, - 0x4073271c, + 0x4071a71e, + 0x40722731, + 0x4072a74a, + 0x40732762, 0x4073936d, - 0x40742730, - 0x4074a74a, - 0x4075275b, - 0x4075a76f, - 0x4076277d, + 0x40742776, + 0x4074a790, + 0x407527a1, + 0x4075a7b5, + 0x407627c3, 0x407691aa, - 0x407727a2, - 0x4077a7c4, - 0x407827df, - 0x4078a818, - 0x4079282f, - 0x4079a845, - 0x407a2851, - 0x407aa864, - 0x407b2879, - 0x407ba88b, - 0x407c28a0, - 0x407ca8a9, - 0x407d2152, + 0x407727e8, + 0x4077a80a, + 0x40782825, + 0x4078a85e, + 0x40792875, + 0x4079a88b, + 0x407a2897, + 0x407aa8aa, + 0x407b28bf, + 0x407ba8d1, + 0x407c28e6, + 0x407ca8ef, + 0x407d2162, 0x407d9c57, - 0x407e27f4, + 0x407e283a, 0x407e9e16, 0x407f1a67, 0x407f9887, @@ -504,42 +504,45 @@ 0x40809a8f, 0x40811cd9, 0x40819c08, - 0x40822635, + 0x4082267b, 0x4082986d, 0x40831df1, - 0x4083a028, + 0x4083a038, 0x40841aa3, 0x40849e4e, - 0x41f4228b, - 0x41f9231d, - 0x41fe2210, - 0x41fea3ec, - 0x41ff24dd, - 0x420322a4, - 0x420822c6, - 0x4208a302, - 0x420921f4, - 0x4209a33c, - 0x420a224b, - 0x420aa22b, - 0x420b226b, - 0x420ba2e4, - 0x420c24f9, - 0x420ca3b9, - 0x420d23d3, - 0x420da40a, - 0x42122424, - 0x421724c0, - 0x4217a466, - 0x421c2488, - 0x421f2443, - 0x42212510, - 0x422624a3, - 0x422b25a9, - 0x422ba572, - 0x422c2591, - 0x422ca54c, - 0x422d252b, + 0x40851ed3, + 0x41f4229b, + 0x41f9232d, + 0x41fe2220, + 0x41fea3fc, + 0x41ff24ed, + 0x420322b4, + 0x420822d6, + 0x4208a312, + 0x42092204, + 0x4209a34c, + 0x420a225b, + 0x420aa23b, + 0x420b227b, + 0x420ba2f4, + 0x420c2509, + 0x420ca3c9, + 0x420d23e3, + 0x420da41a, + 0x42122434, + 0x421724d0, + 0x4217a476, + 0x421c2498, + 0x421f2453, + 0x42212520, + 0x422624b3, + 0x422b25ef, + 0x422ba59d, + 0x422c25d7, + 0x422ca55c, + 0x422d253b, + 0x422da5bc, + 0x422e2582, 0x4432072b, 0x4432873a, 0x44330746, @@ -582,69 +585,69 @@ 0x4c3d136d, 0x4c3d937c, 0x4c3e1389, - 0x50322b22, - 0x5032ab31, - 0x50332b3c, - 0x5033ab4c, - 0x50342b65, - 0x5034ab7f, - 0x50352b8d, - 0x5035aba3, - 0x50362bb5, - 0x5036abcb, - 0x50372be4, - 0x5037abf7, - 0x50382c0f, - 0x5038ac20, - 0x50392c35, - 0x5039ac49, - 0x503a2c69, - 0x503aac7f, - 0x503b2c97, - 0x503baca9, - 0x503c2cc5, - 0x503cacdc, - 0x503d2cf5, - 0x503dad0b, - 0x503e2d18, - 0x503ead2e, - 0x503f2d40, + 0x50322b68, + 0x5032ab77, + 0x50332b82, + 0x5033ab92, + 0x50342bab, + 0x5034abc5, + 0x50352bd3, + 0x5035abe9, + 0x50362bfb, + 0x5036ac11, + 0x50372c2a, + 0x5037ac3d, + 0x50382c55, + 0x5038ac66, + 0x50392c7b, + 0x5039ac8f, + 0x503a2caf, + 0x503aacc5, + 0x503b2cdd, + 0x503bacef, + 0x503c2d0b, + 0x503cad22, + 0x503d2d3b, + 0x503dad51, + 0x503e2d5e, + 0x503ead74, + 0x503f2d86, 0x503f8382, - 0x50402d53, - 0x5040ad63, - 0x50412d7d, - 0x5041ad8c, - 0x50422da6, - 0x5042adc3, - 0x50432dd3, - 0x5043ade3, - 0x50442df2, + 0x50402d99, + 0x5040ada9, + 0x50412dc3, + 0x5041add2, + 0x50422dec, + 0x5042ae09, + 0x50432e19, + 0x5043ae29, + 0x50442e38, 0x5044843f, - 0x50452e06, - 0x5045ae24, - 0x50462e37, - 0x5046ae4d, - 0x50472e5f, - 0x5047ae74, - 0x50482e9a, - 0x5048aea8, - 0x50492ebb, - 0x5049aed0, - 0x504a2ee6, - 0x504aaef6, - 0x504b2f16, - 0x504baf29, - 0x504c2f4c, - 0x504caf7a, - 0x504d2f8c, - 0x504dafa9, - 0x504e2fc4, - 0x504eafe0, - 0x504f2ff2, - 0x504fb009, - 0x50503018, + 0x50452e4c, + 0x5045ae6a, + 0x50462e7d, + 0x5046ae93, + 0x50472ea5, + 0x5047aeba, + 0x50482ee0, + 0x5048aeee, + 0x50492f01, + 0x5049af16, + 0x504a2f2c, + 0x504aaf3c, + 0x504b2f5c, + 0x504baf6f, + 0x504c2f92, + 0x504cafc0, + 0x504d2fd2, + 0x504dafef, + 0x504e300a, + 0x504eb026, + 0x504f3038, + 0x504fb04f, + 0x5050305e, 0x505086ef, - 0x5051302b, + 0x50513071, 0x58320ec9, 0x68320e8b, 0x68328c25, @@ -1079,6 +1082,7 @@ "NO_RENEGOTIATION\0" "NO_REQUIRED_DIGEST\0" "NO_SHARED_CIPHER\0" + "NO_SHARED_GROUP\0" "NULL_SSL_CTX\0" "NULL_SSL_METHOD_PASSED\0" "OLD_SESSION_CIPHER_NOT_RETURNED\0" @@ -1139,7 +1143,9 @@ "TLSV1_ALERT_USER_CANCELLED\0" "TLSV1_BAD_CERTIFICATE_HASH_VALUE\0" "TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE\0" + "TLSV1_CERTIFICATE_REQUIRED\0" "TLSV1_CERTIFICATE_UNOBTAINABLE\0" + "TLSV1_UNKNOWN_PSK_IDENTITY\0" "TLSV1_UNRECOGNIZED_NAME\0" "TLSV1_UNSUPPORTED_EXTENSION\0" "TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST\0"
diff --git a/third_party/boringssl/linux-x86_64/crypto/ec/p256-x86_64-asm.S b/third_party/boringssl/linux-x86_64/crypto/ec/p256-x86_64-asm.S index 4abce6f9..8a18859 100644 --- a/third_party/boringssl/linux-x86_64/crypto/ec/p256-x86_64-asm.S +++ b/third_party/boringssl/linux-x86_64/crypto/ec/p256-x86_64-asm.S
@@ -625,6 +625,8 @@ movq %r9,%rsi adcq $0,%rdx + + subq $-1,%r8 movq %r10,%rax sbbq %r12,%r9
diff --git a/third_party/boringssl/mac-x86_64/crypto/ec/p256-x86_64-asm.S b/third_party/boringssl/mac-x86_64/crypto/ec/p256-x86_64-asm.S index 1cd0cc3..62dc474 100644 --- a/third_party/boringssl/mac-x86_64/crypto/ec/p256-x86_64-asm.S +++ b/third_party/boringssl/mac-x86_64/crypto/ec/p256-x86_64-asm.S
@@ -624,6 +624,8 @@ movq %r9,%rsi adcq $0,%rdx + + subq $-1,%r8 movq %r10,%rax sbbq %r12,%r9
diff --git a/third_party/boringssl/win-x86_64/crypto/ec/p256-x86_64-asm.asm b/third_party/boringssl/win-x86_64/crypto/ec/p256-x86_64-asm.asm index a2e4075..45df829 100644 --- a/third_party/boringssl/win-x86_64/crypto/ec/p256-x86_64-asm.asm +++ b/third_party/boringssl/win-x86_64/crypto/ec/p256-x86_64-asm.asm
@@ -673,6 +673,8 @@ mov rsi,r9 adc rdx,0 + + sub r8,-1 mov rax,r10 sbb r9,r12
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index d3cf8e0..e860100 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -167,14 +167,6 @@ def GetSvnRevision(svn_repo): """Returns current revision of the svn repo at svn_repo.""" - if sys.platform == 'darwin': - # mac_files toolchain must be set for hermetic builds. - root = os.path.dirname(os.path.dirname(os.path.dirname( - os.path.dirname(__file__)))) - sys.path.append(os.path.join(root, 'build')) - import mac_toolchain - - mac_toolchain.SetToolchainEnvironment() svn_info = subprocess.check_output('svn info ' + svn_repo, shell=True) m = re.search(r'Revision: (\d+)', svn_info) return m.group(1)
diff --git a/tools/gn/bootstrap/bootstrap.py b/tools/gn/bootstrap/bootstrap.py index 5db0f3a1..9fc1c766 100755 --- a/tools/gn/bootstrap/bootstrap.py +++ b/tools/gn/bootstrap/bootstrap.py
@@ -498,7 +498,6 @@ 'base/trace_event/process_memory_totals.cc', 'base/trace_event/trace_buffer.cc', 'base/trace_event/trace_config.cc', - 'base/trace_event/trace_event.cc', 'base/trace_event/trace_event_argument.cc', 'base/trace_event/trace_event_impl.cc', 'base/trace_event/trace_event_memory_overhead.cc', @@ -536,7 +535,6 @@ 'base/sys_info_posix.cc', 'base/threading/platform_thread_internal_posix.cc', 'base/threading/platform_thread_posix.cc', - 'base/threading/thread_local_posix.cc', 'base/threading/thread_local_storage_posix.cc', 'base/threading/worker_pool_posix.cc', 'base/time/time_posix.cc',
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 8bc5849..cb8a0b46 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -180,6 +180,7 @@ 'Mac deterministic (dbg)': 'debug_bot', 'Mojo ChromiumOS': 'chromeos_with_codecs_ozone_release_trybot', 'Mojo Windows': 'release_bot_x86', + 'Site Isolation Android': 'android_release_bot_minimal_symbols_arm64', 'Site Isolation Linux': 'release_trybot', 'Site Isolation Win': 'release_trybot_x86', 'ThinLTO Linux ToT': 'thin_lto_clang_tot_release_static',
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index c347a3d..1946de11 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -29779,6 +29779,9 @@ <histogram name="Net.ErrorResponseHasContentMainFrame" enum="BooleanSuccess"> <owner>mmenke@chromium.org</owner> + <obsolete> + Deprecated 10/2016. + </obsolete> <summary> The number of main frame 4xx/5xx responses that have content, to determine if it's worth hooking up an error page for those that don't. Intended to be @@ -29788,6 +29791,9 @@ <histogram name="Net.ErrorResponseHasContentNonMainFrame" enum="BooleanSuccess"> <owner>mmenke@chromium.org</owner> + <obsolete> + Deprecated 10/2016. + </obsolete> <summary> The number of non-main frame 4xx/5xx responses that have content, to determine if it's worth hooking up an error page for those that don't. @@ -30405,6 +30411,9 @@ <histogram name="Net.HttpProxySocketRequestTime" units="ms"> <owner>mmenke@chromium.org</owner> + <obsolete> + Deprecated as of 10/2016. + </obsolete> <summary>Time it takes to request a new (unused) HTTP proxy socket.</summary> </histogram> @@ -33382,6 +33391,15 @@ </summary> </histogram> +<histogram name="Net.SSL_AuthRootConsistency" enum="SSLAuthRootConsistency"> + <owner>rsleevi@chromium.org</owner> + <summary> + The results of comparing the built-in list of known Windows roots against + the CERT_AUTH_ROOT_SHA256_HASH_PROP_ID certificate property. Recorded for + each certificate verification on Windows. + </summary> +</histogram> + <histogram name="Net.SSL_CipherSuite" enum="SSLCipherSuite"> <owner>agl@chromium.org</owner> <owner>rsleevi@chromium.org</owner> @@ -64332,6 +64350,16 @@ </summary> </histogram> +<histogram name="TaskScheduler.NumTasksBeforeDetach" units="tasks"> + <owner>fdoray@chromium.org</owner> + <owner>gab@chromium.org</owner> + <owner>robliao@chromium.org</owner> + <summary> + Number of tasks executed by a SchedulerWorker before it detached. Recorded + when the SchedulerWorker is woken up after detaching. + </summary> +</histogram> + <histogram name="TaskScheduler.NumTasksBetweenWaits" units="tasks"> <owner>fdoray@chromium.org</owner> <owner>gab@chromium.org</owner> @@ -83887,6 +83915,8 @@ <int value="1648" label="RTCPeerConnectionCreateDataChannelMaxRetransmitTime"/> <int value="1649" label="RTCPeerConnectionCreateDataChannelMaxRetransmits"/> + <int value="1650" label="AudioContextCreateConstantSource"/> + <int value="1651" label="WebAudioConstantSourceNode"/> </enum> <enum name="FetchRequestMode" type="int"> @@ -99125,6 +99155,29 @@ <int value="6" label="Shown from menu."/> </enum> +<enum name="SSLAuthRootConsistency" type="int"> + <summary> + The results of comparing the built-in list of known Windows roots against + programatically detecting the built-in status. + </summary> + <int value="0" label="Not AuthRoot, not built-in"> + Not detected as from AuthRoot, nor built-in + (BUILT_IN_PROPERTY_NOT_FOUND_BUILTIN_NOT_SET) + </int> + <int value="1" label="Not AuthRoot, but built-in"> + Not detected as from AuthRoot, but built-in + (BUILT_IN_PROPERTY_NOT_FOUND_BUILTIN_SET) + </int> + <int value="2" label="AuthRoot, not built-in"> + Detected as from AuthRoot, but not built-in + (BUILT_IN_PROPERTY_FOUND_BUILTIN_NOT_SET) + </int> + <int value="3" label="AuthRoot, built-in"> + Detected as from AuthRoot and also built-in + (BUILT_IN_PROPERTY_FOUND_BUILTIN_SET) + </int> +</enum> + <enum name="SSLCaptivePortal" type="int"> <int value="0" label="All captive portal events (CAPTIVE_PORTAL_ALL)"/> <int value="1" @@ -99309,6 +99362,17 @@ <int value="196" label="TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256"/> <int value="197" label="TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256"/> <int value="255" label="TLS_EMPTY_RENEGOTIATION_INFO_SCSV"/> + <int value="4865" label="TLS_AES_128_GCM_SHA256"/> + <int value="4866" label="TLS_AES_256_GCM_SHA384"/> + <int value="4867" label="TLS_CHACHA20_POLY1305_SHA256"/> + <int value="5815" + label="TLS_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256 (experimental)"/> + <int value="5816" + label="TLS_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (experimental)"/> + <int value="5817" + label="TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384 (experimental)"/> + <int value="5818" + label="TLS_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384 (experimental)"/> <int value="49153" label="TLS_ECDH_ECDSA_WITH_NULL_SHA"/> <int value="49154" label="TLS_ECDH_ECDSA_WITH_RC4_128_SHA"/> <int value="49155" label="TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"/> @@ -110117,6 +110181,7 @@ label="Applies to the ForegroundFileIO worker pool."/> <suffix name="ForegroundPool" label="Applies to the Foreground worker pool."/> <affected-histogram name="TaskScheduler.DetachDuration"/> + <affected-histogram name="TaskScheduler.NumTasksBeforeDetach"/> <affected-histogram name="TaskScheduler.NumTasksBetweenWaits"/> <affected-histogram name="TaskScheduler.TaskLatency"/> </histogram_suffixes>
diff --git a/tools/origin_trials/generate_token.py b/tools/origin_trials/generate_token.py index 268f4567..a79f169 100755 --- a/tools/origin_trials/generate_token.py +++ b/tools/origin_trials/generate_token.py
@@ -8,6 +8,7 @@ usage: generate_token.py [-h] [--key-file KEY_FILE] [--expire-days EXPIRE_DAYS | --expire-timestamp EXPIRE_TIMESTAMP] + [--is_subdomain | --no-subdomain] origin trial_name Run "generate_token.py -h" for more help on usage. @@ -85,10 +86,13 @@ return int(args.expire_timestamp) return (int(time.time()) + (int(args.expire_days) * 86400)) -def GenerateTokenData(origin, api_name, expiry): - return json.dumps({"origin": origin, - "feature": api_name, - "expiry": expiry}).encode('utf-8') +def GenerateTokenData(origin, is_subdomain, feature_name, expiry): + data = {"origin": origin, + "feature": feature_name, + "expiry": expiry} + if is_subdomain is not None: + data["isSubdomain"] = is_subdomain + return json.dumps(data).encode('utf-8') def GenerateDataToSign(version, data): return version + struct.pack(">I",len(data)) + data @@ -104,11 +108,11 @@ default_key_file_absolute = os.path.join(script_dir, DEFAULT_KEY_FILE) parser = argparse.ArgumentParser( - description="Generate tokens for enabling experimental APIs") + description="Generate tokens for enabling experimental features") parser.add_argument("origin", - help="Origin for which to enable the API. This can be " - "either a hostname (default scheme HTTPS, default " - "port 443) or a URL.", + help="Origin for which to enable the feature. This can " + "be either a hostname (default scheme HTTPS, " + "default port 443) or a URL.", type=OriginFromArg) parser.add_argument("trial_name", help="Feature to enable. The current list of " @@ -117,14 +121,28 @@ parser.add_argument("--key-file", help="Ed25519 private key file to sign the token with", default=default_key_file_absolute) + + subdomain_group = parser.add_mutually_exclusive_group() + subdomain_group.add_argument("--is-subdomain", + help="Token will enable the feature for all " + "subdomains that match the origin", + dest="is_subdomain", + action="store_true") + subdomain_group.add_argument("--no-subdomain", + help="Token will only match the specified " + "origin (default behavior)", + dest="is_subdomain", + action="store_false") + parser.set_defaults(is_subdomain=None) + expiry_group = parser.add_mutually_exclusive_group() expiry_group.add_argument("--expire-days", - help="Days from now when the token should exipire", + help="Days from now when the token should expire", type=int, default=42) expiry_group.add_argument("--expire-timestamp", help="Exact time (seconds since 1970-01-01 " - "00:00:00 UTC) when the token should exipire", + "00:00:00 UTC) when the token should expire", type=int) args = parser.parse_args() @@ -141,7 +159,8 @@ print("Unable to use the specified private key file.") sys.exit(1) - token_data = GenerateTokenData(args.origin, args.trial_name, expiry) + token_data = GenerateTokenData(args.origin, args.is_subdomain, + args.trial_name, expiry) data_to_sign = GenerateDataToSign(VERSION, token_data) signature = Sign(private_key, data_to_sign) @@ -157,6 +176,7 @@ # Output the token details print "Token details:" print " Origin: %s" % args.origin + print " Is Subdomain: %s" % args.is_subdomain print " Feature: %s" % args.trial_name print " Expiry: %d (%s UTC)" % (expiry, datetime.utcfromtimestamp(expiry)) print
diff --git a/ui/android/resources/crushed_sprite_resource.cc b/ui/android/resources/crushed_sprite_resource.cc index ee6a6d1..aac7ccc6 100644 --- a/ui/android/resources/crushed_sprite_resource.cc +++ b/ui/android/resources/crushed_sprite_resource.cc
@@ -4,7 +4,6 @@ #include "ui/android/resources/crushed_sprite_resource.h" -#include "cc/resources/scoped_ui_resource.h" #include "cc/trees/layer_tree_host.h" #include "ui/gfx/android/java_bitmap.h" @@ -60,4 +59,8 @@ return src_dst_rects_.size(); } +size_t CrushedSpriteResource::GetAllocatedSizeInBytes() const { + return bitmap_.getSize(); +} + } // namespace ui
diff --git a/ui/android/resources/crushed_sprite_resource.h b/ui/android/resources/crushed_sprite_resource.h index 9ffa25a79..9bfb57bb 100644 --- a/ui/android/resources/crushed_sprite_resource.h +++ b/ui/android/resources/crushed_sprite_resource.h
@@ -16,7 +16,6 @@ namespace cc { class LayerTreeHost; -class ScopedUIResource; typedef int UIResourceId; } @@ -71,9 +70,11 @@ // Returns the total number of frames in the sprite animation. int GetFrameCount(); + // Returns the memory usage of the bitmap. + size_t GetAllocatedSizeInBytes() const; + private: SkBitmap bitmap_; - std::unique_ptr<cc::ScopedUIResource> last_frame_resource_; SrcDstRects src_dst_rects_; gfx::Size unscaled_sprite_size_; gfx::Size scaled_sprite_size_;
diff --git a/ui/android/resources/resource_manager_impl.cc b/ui/android/resources/resource_manager_impl.cc index 5a91ea5..0f8fbdf 100644 --- a/ui/android/resources/resource_manager_impl.cc +++ b/ui/android/resources/resource_manager_impl.cc
@@ -4,6 +4,7 @@ #include "ui/android/resources/resource_manager_impl.h" +#include <inttypes.h> #include <stddef.h> #include <utility> @@ -12,6 +13,10 @@ #include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/memory/ptr_util.h" +#include "base/strings/stringprintf.h" +#include "base/threading/thread_task_runner_handle.h" +#include "base/trace_event/memory_dump_manager.h" +#include "base/trace_event/process_memory_dump.h" #include "base/trace_event/trace_event.h" #include "cc/resources/scoped_ui_resource.h" #include "cc/resources/ui_resource_manager.h" @@ -44,9 +49,14 @@ reinterpret_cast<intptr_t>(this)) .obj()); DCHECK(!java_obj_.is_null()); + base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( + this, "android::ResourceManagerImpl", + base::ThreadTaskRunnerHandle::Get()); } ResourceManagerImpl::~ResourceManagerImpl() { + base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( + this); Java_ResourceManager_destroy(base::android::AttachCurrentThread(), java_obj_); } @@ -287,6 +297,44 @@ return src_dst_rects; } +bool ResourceManagerImpl::OnMemoryDump( + const base::trace_event::MemoryDumpArgs& args, + base::trace_event::ProcessMemoryDump* pmd) { + size_t size = 0; + for (const auto& resource_map : resources_) { + for (const auto& id_and_resource : resource_map) { + if (id_and_resource.second && id_and_resource.second->ui_resource) + size += id_and_resource.second->ui_resource->GetAllocatedSizeInBytes(); + } + } + for (const auto& id_and_resource : crushed_sprite_resources_) { + if (id_and_resource.second) + size += id_and_resource.second->GetAllocatedSizeInBytes(); + } + for (const auto& color_and_resources : tinted_resources_) { + for (const auto& id_and_resource : *color_and_resources.second) { + if (id_and_resource.second && id_and_resource.second->ui_resource) + size += id_and_resource.second->ui_resource->GetAllocatedSizeInBytes(); + } + } + + base::trace_event::MemoryAllocatorDump* dump = pmd->CreateAllocatorDump( + base::StringPrintf("ui/resource_manager_0x%" PRIXPTR, + reinterpret_cast<uintptr_t>(this))); + dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, + base::trace_event::MemoryAllocatorDump::kUnitsBytes, size); + + // Bitmaps are allocated from malloc. + const char* system_allocator_name = + base::trace_event::MemoryDumpManager::GetInstance() + ->system_allocator_pool_name(); + if (system_allocator_name) { + pmd->AddSuballocation(dump->guid(), system_allocator_name); + } + + return true; +} + void ResourceManagerImpl::OnCrushedSpriteResourceReloaded( JNIEnv* env, const JavaRef<jobject>& jobj,
diff --git a/ui/android/resources/resource_manager_impl.h b/ui/android/resources/resource_manager_impl.h index eef9e9d9..1f05576 100644 --- a/ui/android/resources/resource_manager_impl.h +++ b/ui/android/resources/resource_manager_impl.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/macros.h" +#include "base/trace_event/memory_dump_provider.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/android/resources/resource_manager.h" #include "ui/android/ui_android_export.h" @@ -20,7 +21,9 @@ namespace ui { -class UI_ANDROID_EXPORT ResourceManagerImpl : public ResourceManager { +class UI_ANDROID_EXPORT ResourceManagerImpl + : public ResourceManager, + public base::trace_event::MemoryDumpProvider { public: static ResourceManagerImpl* FromJavaObject(jobject jobj); @@ -78,6 +81,10 @@ CrushedSpriteResource::SrcDstRects ProcessCrushedSpriteFrameRects( std::vector<std::vector<int>> frame_rects_vector); + // base::trace_event::MemoryDumpProvider implementation. + bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, + base::trace_event::ProcessMemoryDump* pmd) override; + private: friend class TestResourceManagerImpl;
diff --git a/ui/android/resources/resource_manager_impl_unittest.cc b/ui/android/resources/resource_manager_impl_unittest.cc index 72fd7e0..ac5b471 100644 --- a/ui/android/resources/resource_manager_impl_unittest.cc +++ b/ui/android/resources/resource_manager_impl_unittest.cc
@@ -5,6 +5,9 @@ #include <stddef.h> #include "base/macros.h" +#include "base/message_loop/message_loop.h" +#include "base/trace_event/memory_dump_manager.h" +#include "base/trace_event/process_memory_dump.h" #include "cc/animation/animation_host.h" #include "cc/resources/ui_resource_bitmap.h" #include "cc/resources/ui_resource_manager.h" @@ -111,12 +114,12 @@ } private: + base::MessageLoop message_loop_; WindowAndroid* window_android_; protected: MockUIResourceManager ui_resource_manager_; TestResourceManagerImpl resource_manager_; - cc::TestTaskGraphRunner task_graph_runner_; cc::StubLayerTreeHostClient stub_client_; }; @@ -177,4 +180,25 @@ } } +TEST_F(ResourceManagerTest, TestOnMemoryDumpEmitsData) { + SetResourceAsLoaded(kTestResourceType); + + base::trace_event::MemoryDumpArgs dump_args = { + base::trace_event::MemoryDumpLevelOfDetail::DETAILED}; + std::unique_ptr<base::trace_event::ProcessMemoryDump> process_memory_dump = + base::MakeUnique<base::trace_event::ProcessMemoryDump>(nullptr, + dump_args); + resource_manager_.OnMemoryDump(dump_args, process_memory_dump.get()); + const auto& allocator_dumps = process_memory_dump->allocator_dumps(); + const char* system_allocator_pool_name = + base::trace_event::MemoryDumpManager::GetInstance() + ->system_allocator_pool_name(); + size_t expected_dump_count = system_allocator_pool_name ? 2 : 1; + EXPECT_EQ(expected_dump_count, allocator_dumps.size()); + for (const auto& dump : allocator_dumps) { + ASSERT_TRUE(dump.first.find("ui/resource_manager") == 0 || + dump.first.find(system_allocator_pool_name) == 0); + } +} + } // namespace ui
diff --git a/ui/arc/notification/arc_notification_manager.cc b/ui/arc/notification/arc_notification_manager.cc index 6be7253..d940c58 100644 --- a/ui/arc/notification/arc_notification_manager.cc +++ b/ui/arc/notification/arc_notification_manager.cc
@@ -11,6 +11,7 @@ #include "ash/common/wm_shell.h" #include "base/memory/ptr_util.h" #include "base/stl_util.h" +#include "components/arc/arc_bridge_service.h" #include "mojo/common/common_type_converters.h" #include "ui/arc/notification/arc_custom_notification_item.h" #include "ui/arc/notification/arc_notification_item.h" @@ -176,7 +177,7 @@ return; } - arc::mojom::ArcNotificationEvent command; + mojom::ArcNotificationEvent command; switch (button_index) { case 0: command = mojom::ArcNotificationEvent::BUTTON_1_CLICKED;
diff --git a/ui/arc/notification/arc_notification_manager.h b/ui/arc/notification/arc_notification_manager.h index d8932e1..fc1dd0f 100644 --- a/ui/arc/notification/arc_notification_manager.h +++ b/ui/arc/notification/arc_notification_manager.h
@@ -5,10 +5,10 @@ #ifndef UI_ARC_NOTIFICATION_ARC_NOTIFICATION_MANAGER_H_ #define UI_ARC_NOTIFICATION_ARC_NOTIFICATION_MANAGER_H_ +#include <memory> #include <string> #include <unordered_map> -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" #include "components/arc/common/notifications.mojom.h" #include "components/arc/instance_holder.h" @@ -18,6 +18,7 @@ namespace arc { +class ArcBridgeService; class ArcNotificationItem; class ArcNotificationManager @@ -62,7 +63,7 @@ bool ready_ = false; - mojo::Binding<arc::mojom::NotificationsHost> binding_; + mojo::Binding<mojom::NotificationsHost> binding_; DISALLOW_COPY_AND_ASSIGN(ArcNotificationManager); };
diff --git a/ui/aura/gestures/gesture_recognizer_unittest.cc b/ui/aura/gestures/gesture_recognizer_unittest.cc index e0ec5abe..cb152db 100644 --- a/ui/aura/gestures/gesture_recognizer_unittest.cc +++ b/ui/aura/gestures/gesture_recognizer_unittest.cc
@@ -685,6 +685,33 @@ DISALLOW_COPY_AND_ASSIGN(GestureRecognizerWithSwitchTest); }; +// Verify that we do not crash when removing a window during a cancel touch +// event originating from CancelActiveTouchesExcept. This monitors for +// regressions on crbug.com/651258. +TEST_F(GestureRecognizerTest, TouchCancelCanDestroyWindow) { + auto delegate = base::MakeUnique<GestureEventConsumeDelegate>(); + TimedEvents tes; + const int kTouchId = 1; + + // Create a window that will remove itself from its parent on touch cancelled + // events. + std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate( + delegate.get(), -1234, gfx::Rect(0, 0, 200, 200), root_window())); + auto handler = base::MakeUnique<RemoveOnTouchCancelHandler>(); + window->AddPreTargetHandler(handler.get()); + + // Dispatch an event to |host_window| that will be cancelled. + ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(101, 101), + kTouchId, tes.Now()); + DispatchEventUsingWindowDispatcher(&press); + + // Cancel event, verify there is no crash. + ui::GestureRecognizer::Get()->CancelActiveTouchesExcept(nullptr); + + EXPECT_EQ(1, handler->touch_cancelled_count()); + EXPECT_EQ(nullptr, window->parent()); +} + // Check that appropriate touch events generate tap gesture events. TEST_F(GestureRecognizerTest, GestureEventTap) { std::unique_ptr<GestureEventConsumeDelegate> delegate(
diff --git a/ui/aura/window.cc b/ui/aura/window.cc index 2d7a0487..5966d2e 100644 --- a/ui/aura/window.cc +++ b/ui/aura/window.cc
@@ -144,11 +144,9 @@ if (delegate_) delegate_->OnWindowDestroyed(this); - base::ObserverListBase<WindowObserver>::Iterator iter(&observers_); - for (WindowObserver* observer = iter.GetNext(); observer; - observer = iter.GetNext()) { - RemoveObserver(observer); - observer->OnWindowDestroyed(this); + for (WindowObserver& observer : observers_) { + RemoveObserver(&observer); + observer.OnWindowDestroyed(this); } // Delete the LayoutManager before properties. This way if the LayoutManager
diff --git a/ui/base/models/list_model.h b/ui/base/models/list_model.h index 8778784..d55719c 100644 --- a/ui/base/models/list_model.h +++ b/ui/base/models/list_model.h
@@ -100,27 +100,23 @@ } void NotifyItemsAdded(size_t start, size_t count) { - FOR_EACH_OBSERVER(ListModelObserver, - observers_, - ListItemsAdded(start, count)); + for (ListModelObserver& observer : observers_) + observer.ListItemsAdded(start, count); } void NotifyItemsRemoved(size_t start, size_t count) { - FOR_EACH_OBSERVER(ListModelObserver, - observers_, - ListItemsRemoved(start, count)); + for (ListModelObserver& observer : observers_) + observer.ListItemsRemoved(start, count); } void NotifyItemMoved(size_t index, size_t target_index) { - FOR_EACH_OBSERVER(ListModelObserver, - observers_, - ListItemMoved(index, target_index)); + for (ListModelObserver& observer : observers_) + observer.ListItemMoved(index, target_index); } void NotifyItemsChanged(size_t start, size_t count) { - FOR_EACH_OBSERVER(ListModelObserver, - observers_, - ListItemsChanged(start, count)); + for (ListModelObserver& observer : observers_) + observer.ListItemsChanged(start, count); } size_t item_count() const { return items_.size(); }
diff --git a/ui/base/models/tree_node_model.h b/ui/base/models/tree_node_model.h index 3cb290a3..a61abd98f 100644 --- a/ui/base/models/tree_node_model.h +++ b/ui/base/models/tree_node_model.h
@@ -229,21 +229,18 @@ } void NotifyObserverTreeNodesAdded(NodeType* parent, int start, int count) { - FOR_EACH_OBSERVER(TreeModelObserver, - observer_list_, - TreeNodesAdded(this, parent, start, count)); + for (TreeModelObserver& observer : observer_list_) + observer.TreeNodesAdded(this, parent, start, count); } void NotifyObserverTreeNodesRemoved(NodeType* parent, int start, int count) { - FOR_EACH_OBSERVER(TreeModelObserver, - observer_list_, - TreeNodesRemoved(this, parent, start, count)); + for (TreeModelObserver& observer : observer_list_) + observer.TreeNodesRemoved(this, parent, start, count); } void NotifyObserverTreeNodeChanged(TreeModelNode* node) { - FOR_EACH_OBSERVER(TreeModelObserver, - observer_list_, - TreeNodeChanged(this, node)); + for (TreeModelObserver& observer : observer_list_) + observer.TreeNodeChanged(this, node); } // TreeModel:
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc index 89c66972..1afdea4 100644 --- a/ui/compositor/compositor.cc +++ b/ui/compositor/compositor.cc
@@ -214,11 +214,11 @@ CancelCompositorLock(); DCHECK(!compositor_lock_); - FOR_EACH_OBSERVER(CompositorObserver, observer_list_, - OnCompositingShuttingDown(this)); + for (auto& observer : observer_list_) + observer.OnCompositingShuttingDown(this); - FOR_EACH_OBSERVER(CompositorAnimationObserver, animation_observer_list_, - OnCompositingShuttingDown(this)); + for (auto& observer : animation_observer_list_) + observer.OnCompositingShuttingDown(this); if (root_layer_) root_layer_->ResetCompositor(); @@ -443,9 +443,8 @@ } void Compositor::BeginMainFrame(const cc::BeginFrameArgs& args) { - FOR_EACH_OBSERVER(CompositorAnimationObserver, - animation_observer_list_, - OnAnimationStep(args.frame_time)); + for (auto& observer : animation_observer_list_) + observer.OnAnimationStep(args.frame_time); if (animation_observer_list_.might_have_observers()) host_->SetNeedsAnimate(); } @@ -483,29 +482,27 @@ void Compositor::DidCommit() { DCHECK(!IsLocked()); - FOR_EACH_OBSERVER(CompositorObserver, - observer_list_, - OnCompositingDidCommit(this)); + for (auto& observer : observer_list_) + observer.OnCompositingDidCommit(this); } void Compositor::DidCommitAndDrawFrame() { } void Compositor::DidCompleteSwapBuffers() { - FOR_EACH_OBSERVER(CompositorObserver, observer_list_, - OnCompositingEnded(this)); + for (auto& observer : observer_list_) + observer.OnCompositingEnded(this); } void Compositor::DidPostSwapBuffers() { base::TimeTicks start_time = base::TimeTicks::Now(); - FOR_EACH_OBSERVER(CompositorObserver, observer_list_, - OnCompositingStarted(this, start_time)); + for (auto& observer : observer_list_) + observer.OnCompositingStarted(this, start_time); } void Compositor::DidAbortSwapBuffers() { - FOR_EACH_OBSERVER(CompositorObserver, - observer_list_, - OnCompositingAborted(this)); + for (auto& observer : observer_list_) + observer.OnCompositingAborted(this); } void Compositor::SetOutputIsSecure(bool output_is_secure) { @@ -529,9 +526,8 @@ if (!compositor_lock_) { compositor_lock_ = new CompositorLock(this); host_->SetDeferCommits(true); - FOR_EACH_OBSERVER(CompositorObserver, - observer_list_, - OnCompositingLockStateChanged(this)); + for (auto& observer : observer_list_) + observer.OnCompositingLockStateChanged(this); } return compositor_lock_; } @@ -540,9 +536,8 @@ DCHECK(compositor_lock_); compositor_lock_ = NULL; host_->SetDeferCommits(false); - FOR_EACH_OBSERVER(CompositorObserver, - observer_list_, - OnCompositingLockStateChanged(this)); + for (auto& observer : observer_list_) + observer.OnCompositingLockStateChanged(this); } void Compositor::CancelCompositorLock() {
diff --git a/ui/compositor/compositor_vsync_manager.cc b/ui/compositor/compositor_vsync_manager.cc index f51847c..2bc25fc 100644 --- a/ui/compositor/compositor_vsync_manager.cc +++ b/ui/compositor/compositor_vsync_manager.cc
@@ -39,8 +39,8 @@ void CompositorVSyncManager::NotifyObservers(base::TimeTicks timebase, base::TimeDelta interval) { - FOR_EACH_OBSERVER(CompositorVSyncManager::Observer, observer_list_, - OnUpdateVSyncParameters(timebase, interval)); + for (auto& observer : observer_list_) + observer.OnUpdateVSyncParameters(timebase, interval); } } // namespace ui
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc index 31c5da6..ac205507 100644 --- a/ui/compositor/layer.cc +++ b/ui/compositor/layer.cc
@@ -96,7 +96,8 @@ } Layer::~Layer() { - FOR_EACH_OBSERVER(LayerObserver, observer_list_, LayerDestroyed(this)); + for (auto& observer : observer_list_) + observer.LayerDestroyed(this); // Destroying the animator may cause observers to use the layer (and // indirectly the WebLayer). Destroy the animator first so that the WebLayer @@ -592,7 +593,8 @@ frame_size_in_dip_ = frame_size_in_dip; RecomputeDrawsContentAndUVRect(); - FOR_EACH_OBSERVER(LayerObserver, observer_list_, SurfaceChanged(this)); + for (auto& observer : observer_list_) + observer.SurfaceChanged(this); } void Layer::SetShowSolidColorContent() { @@ -795,8 +797,8 @@ PaintContext(display_list.get(), device_scale_factor_, invalidation)); } display_list->Finalize(); - FOR_EACH_OBSERVER(LayerObserver, observer_list_, - DidPaintLayer(this, invalidation)); + for (auto& observer : observer_list_) + observer.DidPaintLayer(this, invalidation); return display_list; }
diff --git a/ui/compositor/layer_animation_sequence.cc b/ui/compositor/layer_animation_sequence.cc index 041bdbe..50b08e2 100644 --- a/ui/compositor/layer_animation_sequence.cc +++ b/ui/compositor/layer_animation_sequence.cc
@@ -38,9 +38,8 @@ } LayerAnimationSequence::~LayerAnimationSequence() { - FOR_EACH_OBSERVER(LayerAnimationObserver, - observers_, - DetachedFromSequence(this, true)); + for (auto& observer : observers_) + observer.DetachedFromSequence(this, true); } void LayerAnimationSequence::Start(LayerAnimationDelegate* delegate) { @@ -232,15 +231,11 @@ } void LayerAnimationSequence::OnAnimatorDestroyed() { - if (observers_.might_have_observers()) { - base::ObserverListBase<LayerAnimationObserver>::Iterator it(&observers_); - LayerAnimationObserver* obs; - while ((obs = it.GetNext()) != NULL) { - if (!obs->RequiresNotificationWhenAnimatorDestroyed()) { - // Remove the observer, but do not allow notifications to be sent. - observers_.RemoveObserver(obs); - obs->DetachedFromSequence(this, false); - } + for (LayerAnimationObserver& observer : observers_) { + if (!observer.RequiresNotificationWhenAnimatorDestroyed()) { + // Remove the observer, but do not allow notifications to be sent. + observers_.RemoveObserver(&observer); + observer.DetachedFromSequence(this, false); } } } @@ -258,26 +253,23 @@ } void LayerAnimationSequence::NotifyScheduled() { - FOR_EACH_OBSERVER(LayerAnimationObserver, - observers_, - OnLayerAnimationScheduled(this)); + for (auto& observer : observers_) + observer.OnLayerAnimationScheduled(this); } void LayerAnimationSequence::NotifyStarted() { - FOR_EACH_OBSERVER(LayerAnimationObserver, observers_, - OnLayerAnimationStarted(this)); + for (auto& observer : observers_) + observer.OnLayerAnimationStarted(this); } void LayerAnimationSequence::NotifyEnded() { - FOR_EACH_OBSERVER(LayerAnimationObserver, - observers_, - OnLayerAnimationEnded(this)); + for (auto& observer : observers_) + observer.OnLayerAnimationEnded(this); } void LayerAnimationSequence::NotifyAborted() { - FOR_EACH_OBSERVER(LayerAnimationObserver, - observers_, - OnLayerAnimationAborted(this)); + for (auto& observer : observers_) + observer.OnLayerAnimationAborted(this); } LayerAnimationElement* LayerAnimationSequence::CurrentElement() const {
diff --git a/ui/compositor/layer_animator.cc b/ui/compositor/layer_animator.cc index 5af6fb6a..87b852ec 100644 --- a/ui/compositor/layer_animator.cc +++ b/ui/compositor/layer_animator.cc
@@ -872,13 +872,8 @@ } void LayerAnimator::OnScheduled(LayerAnimationSequence* sequence) { - if (observers_.might_have_observers()) { - base::ObserverListBase<LayerAnimationObserver>::Iterator it(&observers_); - LayerAnimationObserver* obs; - while ((obs = it.GetNext()) != NULL) { - sequence->AddObserver(obs); - } - } + for (LayerAnimationObserver& observer : observers_) + sequence->AddObserver(&observer); sequence->OnScheduled(); }
diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc index 77c83c0..4fb3dc7 100644 --- a/ui/compositor/test/in_process_context_factory.cc +++ b/ui/compositor/test/in_process_context_factory.cc
@@ -131,7 +131,8 @@ } void InProcessContextFactory::SendOnLostResources() { - FOR_EACH_OBSERVER(ContextFactoryObserver, observer_list_, OnLostResources()); + for (auto& observer : observer_list_) + observer.OnLostResources(); } void InProcessContextFactory::CreateCompositorFrameSink(
diff --git a/ui/display/BUILD.gn b/ui/display/BUILD.gn index 7fc81d0..9faf6f4 100644 --- a/ui/display/BUILD.gn +++ b/ui/display/BUILD.gn
@@ -77,6 +77,7 @@ deps = [ "//base", + "//third_party/re2", "//ui/display/types", "//ui/display/util", "//ui/gfx", @@ -158,6 +159,8 @@ "chromeos/test/test_display_layout_manager.h", "chromeos/test/test_native_display_delegate.cc", "chromeos/test/test_native_display_delegate.h", + "test/display_matchers.cc", + "test/display_matchers.h", "test/display_test_util.h", "test/test_screen.cc", "test/test_screen.h", @@ -170,6 +173,7 @@ ] deps = [ "//base", + "//testing/gmock", "//ui/display/types", "//ui/gfx", "//ui/gfx:test_support", @@ -190,6 +194,7 @@ "display_change_notifier_unittest.cc", "display_list_unittest.cc", "display_unittest.cc", + "fake_display_snapshot_unittests.cc", "manager/display_layout_builder_unittest.cc", "manager/display_layout_unittest.cc", "manager/display_manager_utilities_unittest.cc", @@ -207,6 +212,7 @@ "//base", "//base/test:run_all_unittests", "//base/test:test_support", + "//testing/gmock", "//testing/gtest", "//ui/display/types", "//ui/display/util",
diff --git a/ui/display/DEPS b/ui/display/DEPS index 047a8e3a..ace5a96 100644 --- a/ui/display/DEPS +++ b/ui/display/DEPS
@@ -1,5 +1,6 @@ include_rules = [ "+mojo/public", "+third_party/cros_system_api", + "+third_party/re2", "+ui/gfx", ]
diff --git a/ui/display/fake_display_delegate.cc b/ui/display/fake_display_delegate.cc index 8f02397..ccfc64d 100644 --- a/ui/display/fake_display_delegate.cc +++ b/ui/display/fake_display_delegate.cc
@@ -4,6 +4,8 @@ #include "ui/display/fake_display_delegate.h" +#include <inttypes.h> + #include <string> #include <utility> @@ -47,7 +49,7 @@ FakeDisplaySnapshot::Builder builder; builder.SetId(id).SetNativeMode(display_size); - builder.SetName(base::StringPrintf("Fake Display %d", next_display_id_)); + builder.SetName(base::StringPrintf("Fake Display %" PRId64, id)); // Add the first display as internal. if (displays_.empty()) @@ -134,7 +136,15 @@ const ui::DisplayMode* mode, const gfx::Point& origin, const ui::ConfigureCallback& callback) { - callback.Run(true); + // Check the display mode is appropriate for the display snapshot. + for (const auto& existing_mode : output.modes()) { + if (existing_mode.get() == mode) { + callback.Run(true); + return; + } + } + + callback.Run(false); } void FakeDisplayDelegate::CreateFrameBuffer(const gfx::Size& size) {} @@ -199,10 +209,13 @@ // Split on commas and parse each display string. for (std::string part : base::SplitString( command_string, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) { + int64_t id = GenerateDisplayID(kReservedManufacturerID, kProductCodeHash, + next_display_id_); std::unique_ptr<ui::DisplaySnapshot> snapshot = - CreateSnapshotFromSpec(part); + FakeDisplaySnapshot::CreateFromSpec(id, part); if (snapshot) { AddDisplay(std::move(snapshot)); + next_display_id_++; } else { LOG(ERROR) << "Failed to parse display \"" << part << "\""; } @@ -211,34 +224,6 @@ return true; } -std::unique_ptr<ui::DisplaySnapshot> -FakeDisplayDelegate::CreateSnapshotFromSpec(const std::string& spec) { - int width = 0; - int height = 0; - int dpi = 0; - - // Width and height are required but DPI is optional. - int found = sscanf(spec.c_str(), "%dx%d^%d", &width, &height, &dpi); - if (found < 2) - return nullptr; - - int64_t id = GenerateDisplayID(kReservedManufacturerID, kProductCodeHash, - ++next_display_id_); - - FakeDisplaySnapshot::Builder builder; - builder.SetId(id).SetNativeMode(gfx::Size(width, height)); - builder.SetName(base::StringPrintf("Fake Display %d", next_display_id_)); - - if (found >= 3) - builder.SetDPI(dpi); - - // TODO(kylechar): Add type to the spec string. - if (displays_.empty()) - builder.SetType(ui::DISPLAY_CONNECTION_TYPE_INTERNAL); - - return builder.Build(); -} - void FakeDisplayDelegate::OnConfigurationChanged() { if (!initialized_) return;
diff --git a/ui/display/fake_display_delegate.h b/ui/display/fake_display_delegate.h index d6d05ed8..8a2c039 100644 --- a/ui/display/fake_display_delegate.h +++ b/ui/display/fake_display_delegate.h
@@ -26,16 +26,40 @@ // configuration and display management code. // // The size and number of displays can controlled via --screen-config=X -// command line flag with the format: -// HxW[^dpi][,] +// command line flag. The format is as follows, where [] are optional: +// native_mode[#other_modes][^dpi][/options] +// +// native_mode: the native display mode, with format: +// HxW[%R] // H: display height in pixels [int] // W: display width in pixels [int] -// dpi: display physical size set based on DPI [int] +// R: display refresh rate [float] // -// Two 800x800 displays: -// --screen-config=800x800,800x800 -// One 1820x1080 display and one 400x400 display: -// --screen-config=1920x1080,400x400 +// other_modes: list of other of display modes, with format: +// #HxW[%R][:HxW[%R]] +// H,W,R: same meaning as in native_mode. +// Note: The first mode is delimited with '#' and any subsequent modes are +// delimited with ':'. +// +// dpi: display DPI used to set physical size, with format: +// ^D +// D: display DPI [int] +// +// options: options to set on display snapshot, with format: +// /[a][c][i][o] +// a: display is aspect preserving [literal a] +// c: display has color correction matrix [literal c] +// i: display is internal [literal i] +// o: display has overscan [literal o] +// +// Examples: +// +// Two 800x800 displays, with first display as internal display: +// --screen-config=800x800/i,800x800 +// One 1920x1080 display as internal display with alternate resolutions: +// --screen-config=1920x1080#1600x900:1280x720/i +// One 1600x900 display with 120 refresh rate and high-DPI: +// --screen-config=1600x900%120^300 // No displays: // --screen-config=none // @@ -89,11 +113,6 @@ FakeDisplayController* GetFakeDisplayController() override; protected: - // Creates a display snapshot from the provided |spec| string. Return null if - // |spec| is invalid. - std::unique_ptr<ui::DisplaySnapshot> CreateSnapshotFromSpec( - const std::string& spec); - // Sets initial display snapshots from command line flag. Returns true if // command line flag was provided. bool InitFromCommandLine();
diff --git a/ui/display/fake_display_snapshot.cc b/ui/display/fake_display_snapshot.cc index a431a2a..f34177d 100644 --- a/ui/display/fake_display_snapshot.cc +++ b/ui/display/fake_display_snapshot.cc
@@ -11,7 +11,12 @@ #include <vector> #include "base/memory/ptr_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" #include "base/strings/stringprintf.h" +#include "third_party/re2/src/re2/re2.h" + +using base::StringPiece; namespace display { @@ -62,6 +67,108 @@ return ""; } +// Extracts text after specified delimiter. If the delimiter doesn't appear +// exactly once the result will be empty and the input string will be +// unmodified. Otherwise, the input string will contain the text before the +// delimiter and the result will be the text after the delimiter. +StringPiece ExtractSuffix(StringPiece* str, StringPiece delimiter) { + std::vector<StringPiece> parts = base::SplitStringPiece( + *str, delimiter, base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + + if (parts.size() == 2) { + *str = parts[0]; + return parts[1]; + } + + return StringPiece(); +} + +// Parses a display mode from |str| in the format HxW[%R], returning null if +// |str| is invalid. +std::unique_ptr<ui::DisplayMode> ParseDisplayMode(const std::string& str) { + int width = 0; + int height = 0; + std::string refresh_rate_str; + + // Check against regex and extract values. + if (!RE2::FullMatch(str, "(\\d+)x(\\d+)(?:%(\\d+\\.?\\d*))?", &width, &height, + &refresh_rate_str)) { + LOG(ERROR) << "Invalid display mode string \"" << str << "\""; + return nullptr; + } + + // Refresh rate is optional and will be be 60 if not specified. + double refresh_rate = 60.0f; + if (!refresh_rate_str.empty() && + !base::StringToDouble(refresh_rate_str, &refresh_rate)) { + LOG(ERROR) << "Unable to parse display mode \"" << str << "\""; + return nullptr; + } + + return base::MakeUnique<ui::DisplayMode>(gfx::Size(width, height), false, + static_cast<float>(refresh_rate)); +} + +// Parses a list of alternate display modes, adding each new display mode to +// |builder|. Returns false if any of the modes are invalid. +bool HandleModes(FakeDisplaySnapshot::Builder* builder, + StringPiece resolutions) { + for (const std::string& mode_str : + base::SplitString(resolutions, ":", base::TRIM_WHITESPACE, + base::SPLIT_WANT_NONEMPTY)) { + std::unique_ptr<ui::DisplayMode> mode = ParseDisplayMode(mode_str); + if (!mode) + return false; + + builder->AddMode(std::move(mode)); + } + + return true; +} + +// Parses device DPI and updates |builder|. Returns false if an invalid DPI +// string is provided. +bool HandleDPI(FakeDisplaySnapshot::Builder* builder, StringPiece dpi) { + if (dpi.empty()) + return true; + + int dpi_value = 0; + if (base::StringToInt(dpi, &dpi_value)) { + builder->SetDPI(dpi_value); + return true; + } + + LOG(ERROR) << "Invalid DPI string \"" << dpi << "\""; + return false; +} + +// Parses a list of display options and set each option true on |builder|. +// Returns false if any invalid options are provided. If an option appears more +// than once it will have no effect the second time. +bool HandleOptions(FakeDisplaySnapshot::Builder* builder, StringPiece options) { + for (size_t i = 0; i < options.size(); ++i) { + switch (options[i]) { + case 'o': + builder->SetHasOverscan(true); + break; + case 'c': + builder->SetHasColorCorrectionMatrix(true); + break; + case 'a': + builder->SetIsAspectPerservingScaling(true); + break; + case 'i': + builder->SetType(ui::DISPLAY_CONNECTION_TYPE_INTERNAL); + break; + default: + LOG(ERROR) << "Invalid option specifier \"" << options[i] << "\""; + return false; + } + } + + return true; +} + } // namespace using Builder = FakeDisplaySnapshot::Builder; @@ -84,10 +191,10 @@ gfx::Size physical_size = gfx::ScaleToRoundedSize(native_mode_->size(), PixelPitchMmFromDPI(dpi_)); - return base::WrapUnique(new FakeDisplaySnapshot( + return base::MakeUnique<FakeDisplaySnapshot>( id_, origin_, physical_size, type_, is_aspect_preserving_scaling_, has_overscan_, has_color_correction_matrix_, name_, product_id_, - std::move(modes_), current_mode_, native_mode_)); + std::move(modes_), current_mode_, native_mode_); } Builder& Builder::SetId(int64_t id) { @@ -100,16 +207,31 @@ return *this; } +Builder& Builder::SetNativeMode(std::unique_ptr<ui::DisplayMode> mode) { + native_mode_ = AddOrFindDisplayMode(std::move(mode)); + return *this; +} + Builder& Builder::SetCurrentMode(const gfx::Size& size) { current_mode_ = AddOrFindDisplayMode(size); return *this; } +Builder& Builder::SetCurrentMode(std::unique_ptr<ui::DisplayMode> mode) { + current_mode_ = AddOrFindDisplayMode(std::move(mode)); + return *this; +} + Builder& Builder::AddMode(const gfx::Size& size) { AddOrFindDisplayMode(size); return *this; } +Builder& Builder::AddMode(std::unique_ptr<ui::DisplayMode> mode) { + AddOrFindDisplayMode(std::move(mode)); + return *this; +} + Builder& Builder::SetOrigin(const gfx::Point& origin) { origin_ = origin; return *this; @@ -169,19 +291,32 @@ return modes_.back().get(); } -FakeDisplaySnapshot::FakeDisplaySnapshot( - int64_t display_id, - const gfx::Point& origin, - const gfx::Size& physical_size, - ui::DisplayConnectionType type, - bool is_aspect_preserving_scaling, - bool has_overscan, - bool has_color_correction_matrix, - std::string display_name, - int64_t product_id, - std::vector<std::unique_ptr<const ui::DisplayMode>> modes, - const ui::DisplayMode* current_mode, - const ui::DisplayMode* native_mode) +const ui::DisplayMode* Builder::AddOrFindDisplayMode( + std::unique_ptr<ui::DisplayMode> mode) { + for (auto& existing : modes_) { + if (mode->size() == existing->size() && + mode->is_interlaced() == existing->is_interlaced() && + mode->refresh_rate() == existing->refresh_rate()) + return existing.get(); + } + + // Not found, insert mode and return. + modes_.push_back(std::move(mode)); + return modes_.back().get(); +} + +FakeDisplaySnapshot::FakeDisplaySnapshot(int64_t display_id, + const gfx::Point& origin, + const gfx::Size& physical_size, + ui::DisplayConnectionType type, + bool is_aspect_preserving_scaling, + bool has_overscan, + bool has_color_correction_matrix, + std::string display_name, + int64_t product_id, + DisplayModeList modes, + const ui::DisplayMode* current_mode, + const ui::DisplayMode* native_mode) : DisplaySnapshot(display_id, origin, physical_size, @@ -200,6 +335,36 @@ FakeDisplaySnapshot::~FakeDisplaySnapshot() {} +// static +std::unique_ptr<ui::DisplaySnapshot> FakeDisplaySnapshot::CreateFromSpec( + int64_t id, + const std::string& spec) { + StringPiece leftover(spec); + + // Cut off end of string at each delimiter to split. + StringPiece options = ExtractSuffix(&leftover, "/"); + StringPiece dpi = ExtractSuffix(&leftover, "^"); + StringPiece resolutions = ExtractSuffix(&leftover, "#"); + + // Leftovers should be just the native mode at this point. + std::unique_ptr<ui::DisplayMode> native_mode = + ParseDisplayMode(leftover.as_string()); + + // Fail without valid native mode. + if (!native_mode) + return nullptr; + + FakeDisplaySnapshot::Builder builder; + builder.SetId(id).SetNativeMode(std::move(native_mode)); + builder.SetName(base::StringPrintf("Fake Display %" PRId64, id)); + + if (!HandleModes(&builder, resolutions) || !HandleDPI(&builder, dpi) || + !HandleOptions(&builder, options)) + return nullptr; + + return builder.Build(); +} + std::string FakeDisplaySnapshot::ToString() const { return base::StringPrintf( "id=%" PRId64
diff --git a/ui/display/fake_display_snapshot.h b/ui/display/fake_display_snapshot.h index 1f17bf8..7135124 100644 --- a/ui/display/fake_display_snapshot.h +++ b/ui/display/fake_display_snapshot.h
@@ -38,11 +38,21 @@ // Adds display mode with |size| and set as native mode. If a display mode // with |size| already exists then it will be reused. Builder& SetNativeMode(const gfx::Size& size); + // Adds display mode and set as native mode. If an existing display mode is + // equivalent to |mode| it will be set as native mode instead. + Builder& SetNativeMode(std::unique_ptr<ui::DisplayMode> mode); // Adds display mode with |size| and set as current mode. If a display mode // with |size| already exists then it will be reused. Builder& SetCurrentMode(const gfx::Size& size); - // Adds display mode with |size| if it doesn't exist. + // Adds display mode and set as current mode. If an existing display mode is + // equivalent to |mode| it will be set as current mode instead. + Builder& SetCurrentMode(std::unique_ptr<ui::DisplayMode> mode); + // Adds display mode with |size| if necessary. If a display mode with |size| + // already exists then it will be reused. Builder& AddMode(const gfx::Size& size); + // Adds |mode| if necessary. If an existing display mode is equivalent to + // |mode| it will not be added. + Builder& AddMode(std::unique_ptr<ui::DisplayMode> mode); Builder& SetOrigin(const gfx::Point& origin); Builder& SetType(ui::DisplayConnectionType type); Builder& SetIsAspectPerservingScaling(bool is_aspect_preserving_scaling); @@ -60,8 +70,12 @@ private: // Returns a display mode with |size|. If there is no existing mode, insert - // a display mode with |size|. + // a display mode with |size| first. const ui::DisplayMode* AddOrFindDisplayMode(const gfx::Size& size); + // Returns a display mode equivalent to |mode|. If there is no equivalent + // display mode, insert |mode| first. + const ui::DisplayMode* AddOrFindDisplayMode( + std::unique_ptr<ui::DisplayMode> mode); int64_t id_ = Display::kInvalidDisplayID; gfx::Point origin_; @@ -72,7 +86,7 @@ bool has_color_correction_matrix_ = false; std::string name_ = "Fake Display"; int64_t product_id_ = DisplaySnapshot::kInvalidProductID; - std::vector<std::unique_ptr<const ui::DisplayMode>> modes_; + DisplayModeList modes_; const ui::DisplayMode* current_mode_ = nullptr; const ui::DisplayMode* native_mode_ = nullptr; @@ -88,11 +102,18 @@ bool has_color_correction_matrix, std::string display_name, int64_t product_id, - std::vector<std::unique_ptr<const ui::DisplayMode>> modes, + DisplayModeList modes, const ui::DisplayMode* current_mode, const ui::DisplayMode* native_mode); ~FakeDisplaySnapshot() override; + // Creates a display snapshot from the provided |spec| string. Returns null if + // |spec| is invalid. See fake_display_delegate.h for |spec| format + // description. + static std::unique_ptr<ui::DisplaySnapshot> CreateFromSpec( + int64_t id, + const std::string& spec); + // DisplaySnapshot: std::string ToString() const override;
diff --git a/ui/display/fake_display_snapshot_unittests.cc b/ui/display/fake_display_snapshot_unittests.cc new file mode 100644 index 0000000..fa78a4e8 --- /dev/null +++ b/ui/display/fake_display_snapshot_unittests.cc
@@ -0,0 +1,141 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/display/fake_display_snapshot.h" + +#include <memory> + +#include "base/macros.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/display/test/display_matchers.h" +#include "ui/display/types/display_snapshot.h" + +using DisplayModeList = ui::DisplaySnapshot::DisplayModeList; +using testing::SizeIs; + +namespace display { + +namespace { + +std::unique_ptr<ui::DisplaySnapshot> CreateSnapshot(const std::string& str) { + return FakeDisplaySnapshot::CreateFromSpec(1, str); +} + +} // namespace + +TEST(FakeDisplaySnapshotTest, SizeOnly) { + auto display = CreateSnapshot("1024x768"); + + ASSERT_THAT(display->modes(), SizeIs(1)); + EXPECT_THAT(*display->native_mode(), IsDisplayMode(1024, 768)); +} + +TEST(FakeDisplaySnapshotTest, DefaultTypeIsUnknown) { + auto display = CreateSnapshot("1024x768"); + + ASSERT_THAT(display->modes(), SizeIs(1)); + EXPECT_EQ(ui::DISPLAY_CONNECTION_TYPE_UNKNOWN, display->type()); +} + +TEST(FakeDisplaySnapshotTest, FullNativeMode) { + auto display = CreateSnapshot("1024x768%120"); + + ASSERT_THAT(display->modes(), SizeIs(1)); + EXPECT_THAT(*display->native_mode(), IsDisplayMode(1024, 768, 120.0f)); +} + +TEST(FakeDisplaySnapshotTest, FullNativeModeWithDPI) { + auto display = CreateSnapshot("1000x1000%120^300"); + + ASSERT_THAT(display->modes(), SizeIs(1)); + EXPECT_THAT(*display->native_mode(), IsDisplayMode(1000, 1000, 120.0f)); + EXPECT_EQ(85, display->physical_size().width()); + EXPECT_EQ(85, display->physical_size().height()); +} + +TEST(FakeDisplaySnapshotTest, InternalDisplayWithSize) { + auto display = CreateSnapshot("1600x900/i"); + + ASSERT_THAT(display->modes(), SizeIs(1)); + EXPECT_THAT(*display->native_mode(), IsDisplayMode(1600, 900)); + EXPECT_EQ(ui::DISPLAY_CONNECTION_TYPE_INTERNAL, display->type()); +} + +TEST(FakeDisplaySnapshotTest, MultipleOptions) { + auto display = CreateSnapshot("1600x900/aci"); + + EXPECT_EQ(ui::DISPLAY_CONNECTION_TYPE_INTERNAL, display->type()); + EXPECT_TRUE(display->has_color_correction_matrix()); + EXPECT_TRUE(display->is_aspect_preserving_scaling()); +} + +TEST(FakeDisplaySnapshotTest, AlternateDisplayModes) { + auto display = CreateSnapshot("1920x1080#1600x900:1280x720/i"); + const DisplayModeList& modes = display->modes(); + + ASSERT_THAT(display->modes(), SizeIs(3)); + EXPECT_THAT(*modes[0], IsDisplayMode(1920, 1080)); + EXPECT_THAT(*modes[1], IsDisplayMode(1600, 900)); + EXPECT_THAT(*modes[2], IsDisplayMode(1280, 720)); + EXPECT_EQ(ui::DISPLAY_CONNECTION_TYPE_INTERNAL, display->type()); +} + +TEST(FakeDisplaySnapshotTest, ComplicatedSpecString) { + auto display = + CreateSnapshot("1920x1080%59.99#1600x900%90:1280x720%120^300/i"); + const DisplayModeList& modes = display->modes(); + + ASSERT_THAT(display->modes(), SizeIs(3)); + EXPECT_THAT(*modes[0], IsDisplayMode(1920, 1080, 59.99f)); + EXPECT_THAT(*modes[1], IsDisplayMode(1600, 900, 90.0f)); + EXPECT_THAT(*modes[2], IsDisplayMode(1280, 720, 120.0f)); + EXPECT_EQ(163, display->physical_size().width()); + EXPECT_EQ(91, display->physical_size().height()); + EXPECT_EQ(ui::DISPLAY_CONNECTION_TYPE_INTERNAL, display->type()); +} + +TEST(FakeDisplaySnapshotTest, BadDisplayMode) { + // Need width and height. + EXPECT_EQ(nullptr, CreateSnapshot("1024")); + // Display height and width should be separated by 'x' not ','. + EXPECT_EQ(nullptr, CreateSnapshot("1024,768")); + // Random 'a' before spec starts. + EXPECT_EQ(nullptr, CreateSnapshot("a1024,768")); + // Need to provide a refresh rate after '%'. + EXPECT_EQ(nullptr, CreateSnapshot("1024,768%")); + EXPECT_EQ(nullptr, CreateSnapshot("1024,768%a")); + // Refresh rate should come before DPI. + EXPECT_EQ(nullptr, CreateSnapshot("1000x1000^300%120")); +} + +TEST(FakeDisplaySnapshotTest, BadDPI) { + // DPI should be an integer value. + EXPECT_EQ(nullptr, CreateSnapshot("1024x768^a")); + EXPECT_EQ(nullptr, CreateSnapshot("1024x768^300d")); +} + +TEST(FakeDisplaySnapshotTest, BadOptions) { + // Need a '/' before options. + EXPECT_EQ(nullptr, CreateSnapshot("1024x768i")); + // Character 'z' is not a valid option. + EXPECT_EQ(nullptr, CreateSnapshot("1600x900/z")); + EXPECT_EQ(nullptr, CreateSnapshot("1600x900/iz")); + // DPI should come before options. + EXPECT_EQ(nullptr, CreateSnapshot("1600x900/i^300")); +} + +TEST(FakeDisplaySnapshotTest, BadOrderOptionsAndModes) { + // Options should come after alternate display modes. + auto display = CreateSnapshot("1920x1080/i#1600x900:1280x720"); + EXPECT_EQ(nullptr, display); +} + +TEST(FakeDisplaySnapshotTest, BadOrderModeSeparator) { + // Reverse the '#' and ':' delimiters for alternate display modes. + auto display = CreateSnapshot("1920x1080:1600x900#1280x720"); + EXPECT_EQ(nullptr, display); +} + +} // namespace display
diff --git a/ui/display/test/display_matchers.cc b/ui/display/test/display_matchers.cc new file mode 100644 index 0000000..9668986 --- /dev/null +++ b/ui/display/test/display_matchers.cc
@@ -0,0 +1,48 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/display/test/display_matchers.h" + +namespace display { + +namespace { + +const float kEpsilon = 0.0001f; + +// Matcher to check DisplayMode size and refresh rate. +class DisplayModeMatcher + : public testing::MatcherInterface<const ui::DisplayMode&> { + public: + DisplayModeMatcher(int width, int height, float refresh_rate) + : size_(width, height), refresh_rate_(refresh_rate) {} + + bool MatchAndExplain(const ui::DisplayMode& mode, + testing::MatchResultListener* listener) const override { + return mode.size() == size_ && + std::fabs(mode.refresh_rate() - refresh_rate_) < kEpsilon; + } + + void DescribeTo(std::ostream* os) const override { + *os << "[" << size_.ToString() << " rate=" << refresh_rate_ << "]"; + } + + void DescribeNegationTo(std::ostream* os) const override { + *os << "not [" << size_.ToString() << " rate=" << refresh_rate_ << "]"; + } + + private: + gfx::Size size_; + float refresh_rate_; +}; + +} // namespace + +testing::Matcher<const ui::DisplayMode&> IsDisplayMode(int width, + int height, + float refresh_rate) { + return testing::MakeMatcher( + new DisplayModeMatcher(width, height, refresh_rate)); +} + +} // namespace display
diff --git a/ui/display/test/display_matchers.h b/ui/display/test/display_matchers.h new file mode 100644 index 0000000..42aefa1628 --- /dev/null +++ b/ui/display/test/display_matchers.h
@@ -0,0 +1,19 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_DISPLAY_TEST_DISPLAY_MATCHERS_H_ +#define UI_DISPLAY_TEST_DISPLAY_MATCHERS_H_ + +#include "testing/gmock/include/gmock/gmock.h" +#include "ui/display/types/display_mode.h" + +namespace display { + +// Matcher for DisplayMode size and refresh rate. +testing::Matcher<const ui::DisplayMode&> +IsDisplayMode(int width, int height, float refresh_rate = 60.0f); + +} // namespace display + +#endif // UI_DISPLAY_TEST_DISPLAY_MATCHERS_H_
diff --git a/ui/display/types/display_mode.cc b/ui/display/types/display_mode.cc index daddf68..a1f615a 100644 --- a/ui/display/types/display_mode.cc +++ b/ui/display/types/display_mode.cc
@@ -32,4 +32,8 @@ refresh_rate_); } +void PrintTo(const DisplayMode& mode, std::ostream* os) { + *os << mode.ToString(); +} + } // namespace ui
diff --git a/ui/display/types/display_mode.h b/ui/display/types/display_mode.h index 95bb3bb9..53fc0ad 100644 --- a/ui/display/types/display_mode.h +++ b/ui/display/types/display_mode.h
@@ -6,6 +6,7 @@ #define UI_DISPLAY_TYPES_DISPLAY_MODE_H_ #include <memory> +#include <ostream> #include <string> #include "base/macros.h" @@ -36,6 +37,9 @@ DISALLOW_COPY_AND_ASSIGN(DisplayMode); }; +// Used to by gtest to print readable errors. +DISPLAY_TYPES_EXPORT void PrintTo(const DisplayMode& mode, std::ostream* os); + } // namespace ui #endif // UI_DISPLAY_TYPES_DISPLAY_MODE_H_
diff --git a/ui/display/types/display_snapshot.cc b/ui/display/types/display_snapshot.cc index b833237..67e4b308 100644 --- a/ui/display/types/display_snapshot.cc +++ b/ui/display/types/display_snapshot.cc
@@ -18,20 +18,19 @@ } // namespace -DisplaySnapshot::DisplaySnapshot( - int64_t display_id, - const gfx::Point& origin, - const gfx::Size& physical_size, - DisplayConnectionType type, - bool is_aspect_preserving_scaling, - bool has_overscan, - bool has_color_correction_matrix, - std::string display_name, - const base::FilePath& sys_path, - std::vector<std::unique_ptr<const DisplayMode>> modes, - const std::vector<uint8_t>& edid, - const DisplayMode* current_mode, - const DisplayMode* native_mode) +DisplaySnapshot::DisplaySnapshot(int64_t display_id, + const gfx::Point& origin, + const gfx::Size& physical_size, + DisplayConnectionType type, + bool is_aspect_preserving_scaling, + bool has_overscan, + bool has_color_correction_matrix, + std::string display_name, + const base::FilePath& sys_path, + DisplayModeList modes, + const std::vector<uint8_t>& edid, + const DisplayMode* current_mode, + const DisplayMode* native_mode) : display_id_(display_id), origin_(origin), physical_size_(physical_size),
diff --git a/ui/display/types/display_snapshot.h b/ui/display/types/display_snapshot.h index 58cdb398..2197f70c3 100644 --- a/ui/display/types/display_snapshot.h +++ b/ui/display/types/display_snapshot.h
@@ -24,6 +24,8 @@ // identifiers required to configure this display. class DISPLAY_TYPES_EXPORT DisplaySnapshot { public: + using DisplayModeList = std::vector<std::unique_ptr<const DisplayMode>>; + DisplaySnapshot(int64_t display_id, const gfx::Point& origin, const gfx::Size& physical_size, @@ -33,7 +35,7 @@ bool has_color_correction_matrix, std::string display_name, const base::FilePath& sys_path, - std::vector<std::unique_ptr<const DisplayMode>> modes, + DisplayModeList modes, const std::vector<uint8_t>& edid, const DisplayMode* current_mode, const DisplayMode* native_mode); @@ -56,9 +58,7 @@ int64_t product_id() const { return product_id_; } const gfx::Size& maximum_cursor_size() const { return maximum_cursor_size_; } - const std::vector<std::unique_ptr<const DisplayMode>>& modes() const { - return modes_; - } + const DisplayModeList& modes() const { return modes_; } const std::vector<uint8_t>& edid() const { return edid_; } void set_current_mode(const DisplayMode* mode) { current_mode_ = mode; } @@ -102,7 +102,7 @@ base::FilePath sys_path_; - std::vector<std::unique_ptr<const DisplayMode>> modes_; + DisplayModeList modes_; // The display's EDID. It can be empty if nothing extracted such as in the // case of a virtual display. @@ -120,6 +120,7 @@ // Maximum supported cursor size on this display. gfx::Size maximum_cursor_size_; + private: DISALLOW_COPY_AND_ASSIGN(DisplaySnapshot); };
diff --git a/ui/events/gestures/gesture_recognizer_impl.cc b/ui/events/gestures/gesture_recognizer_impl.cc index 9f948608..5d3e546e 100644 --- a/ui/events/gestures/gesture_recognizer_impl.cc +++ b/ui/events/gestures/gesture_recognizer_impl.cc
@@ -111,11 +111,19 @@ void GestureRecognizerImpl::CancelActiveTouchesExcept( GestureConsumer* not_cancelled) { - for (const auto& consumer_provider : consumer_gesture_provider_) { - if (consumer_provider.first == not_cancelled) + // Do not iterate directly over |consumer_gesture_provider_| because canceling + // active touches may cause the consumer to be removed from + // |consumer_gesture_provider_|. See crbug.com/651258 for more info. + std::vector<GestureConsumer*> consumers(consumer_gesture_provider_.size()); + for (auto entry : consumer_gesture_provider_) { + if (entry.first == not_cancelled) continue; - CancelActiveTouches(consumer_provider.first); + + consumers.push_back(entry.first); } + + for (auto consumer : consumers) + CancelActiveTouches(consumer); } void GestureRecognizerImpl::TransferEventsTo(
diff --git a/ui/events/ozone/evdev/input_device_factory_evdev.cc b/ui/events/ozone/evdev/input_device_factory_evdev.cc index f2e26637..6bf3bbd 100644 --- a/ui/events/ozone/evdev/input_device_factory_evdev.cc +++ b/ui/events/ozone/evdev/input_device_factory_evdev.cc
@@ -39,9 +39,6 @@ namespace { -typedef base::Callback<void(std::unique_ptr<EventConverterEvdev>)> - OpenInputDeviceReplyCallback; - struct OpenInputDeviceParams { // Unique identifier for the new device. int id; @@ -49,10 +46,10 @@ // Device path to open. base::FilePath path; - // Dispatcher for events. Call on UI thread only. + // Dispatcher for events. DeviceEventDispatcherEvdev* dispatcher; - // State shared between devices. Must not be dereferenced on worker thread. + // State shared between devices. CursorDelegateEvdev* cursor; #if defined(USE_EVDEV_GESTURES) GesturePropertyProvider* gesture_property_provider; @@ -120,26 +117,16 @@ fd, params.path, params.id, devinfo, params.cursor, params.dispatcher)); } -// Open an input device. Opening may put the calling thread to sleep, and -// therefore should be run on a thread where latency is not critical. We -// run it on a thread from the worker pool. -// -// This takes a TaskRunner and runs the reply on that thread, so that we -// can hop threads if necessary (back to the UI thread). -void OpenInputDevice(std::unique_ptr<OpenInputDeviceParams> params, - scoped_refptr<base::TaskRunner> reply_runner, - const OpenInputDeviceReplyCallback& reply_callback) { - const base::FilePath& path = params->path; - std::unique_ptr<EventConverterEvdev> converter; - +// Open an input device and construct an EventConverterEvdev. +std::unique_ptr<EventConverterEvdev> OpenInputDevice( + const OpenInputDeviceParams& params) { + const base::FilePath& path = params.path; TRACE_EVENT1("evdev", "OpenInputDevice", "path", path.value()); int fd = open(path.value().c_str(), O_RDWR | O_NONBLOCK); if (fd < 0) { - PLOG(ERROR) << "Cannot open '" << path.value(); - reply_runner->PostTask( - FROM_HERE, base::Bind(reply_callback, base::Passed(&converter))); - return; + PLOG(ERROR) << "Cannot open " << path.value(); + return nullptr; } // Use monotonic timestamps for events. The touch code in particular @@ -153,25 +140,10 @@ if (!devinfo.Initialize(fd, path)) { LOG(ERROR) << "Failed to get device information for " << path.value(); close(fd); - reply_runner->PostTask( - FROM_HERE, base::Bind(reply_callback, base::Passed(&converter))); - return; + return nullptr; } - converter = CreateConverter(*params, fd, devinfo); - - // Reply with the constructed converter. - reply_runner->PostTask(FROM_HERE, - base::Bind(reply_callback, base::Passed(&converter))); -} - -// Close an input device. Closing may put the calling thread to sleep, and -// therefore should be run on a thread where latency is not critical. We -// run it on the FILE thread. -void CloseInputDevice(const base::FilePath& path, - std::unique_ptr<EventConverterEvdev> converter) { - TRACE_EVENT1("evdev", "CloseInputDevice", "path", path.value()); - converter.reset(); + return CreateConverter(params, fd, devinfo); } } // namespace @@ -194,27 +166,24 @@ void InputDeviceFactoryEvdev::AddInputDevice(int id, const base::FilePath& path) { - std::unique_ptr<OpenInputDeviceParams> params(new OpenInputDeviceParams); - params->id = id; - params->path = path; - params->cursor = cursor_; - params->dispatcher = dispatcher_.get(); + OpenInputDeviceParams params; + params.id = id; + params.path = path; + params.cursor = cursor_; + params.dispatcher = dispatcher_.get(); #if defined(USE_EVDEV_GESTURES) - params->gesture_property_provider = gesture_property_provider_.get(); + params.gesture_property_provider = gesture_property_provider_.get(); #endif - OpenInputDeviceReplyCallback reply_callback = + std::unique_ptr<EventConverterEvdev> converter = OpenInputDevice(params); + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&InputDeviceFactoryEvdev::AttachInputDevice, - weak_ptr_factory_.GetWeakPtr()); + weak_ptr_factory_.GetWeakPtr(), base::Passed(&converter))); ++pending_device_changes_; - - // Dispatch task to open from the worker pool, since open may block. - base::WorkerPool::PostTask(FROM_HERE, - base::Bind(&OpenInputDevice, base::Passed(¶ms), - task_runner_, reply_callback), - false /* task_is_slow */); } void InputDeviceFactoryEvdev::RemoveInputDevice(const base::FilePath& path) { @@ -272,17 +241,11 @@ // Disable the device (to release keys/buttons/etc). converter->SetEnabled(false); - // Cancel libevent notifications from this converter. This part must be - // on UI since the polling happens on UI. + // Cancel libevent notifications from this converter. converter->Stop(); UpdateDirtyFlags(converter.get()); NotifyDevicesUpdated(); - - // Dispatch task to close from the worker pool, since close may block. - base::WorkerPool::PostTask( - FROM_HERE, - base::Bind(&CloseInputDevice, path, base::Passed(&converter)), true); } }
diff --git a/ui/events/ozone/evdev/input_device_factory_evdev.h b/ui/events/ozone/evdev/input_device_factory_evdev.h index 30a8a49..d73b2ff 100644 --- a/ui/events/ozone/evdev/input_device_factory_evdev.h +++ b/ui/events/ozone/evdev/input_device_factory_evdev.h
@@ -71,10 +71,10 @@ void EnablePalmSuppression(bool enabled); private: - // Open device at path & starting processing events (on UI thread). + // Open device at path & starting processing events. void AttachInputDevice(std::unique_ptr<EventConverterEvdev> converter); - // Close device at path (on UI thread). + // Close device at path. void DetachInputDevice(const base::FilePath& file_path); // Sync input_device_settings_ to attached devices.
diff --git a/ui/events/ozone/evdev/touch_event_converter_evdev.cc b/ui/events/ozone/evdev/touch_event_converter_evdev.cc index 36fe49b..98483d3 100644 --- a/ui/events/ozone/evdev/touch_event_converter_evdev.cc +++ b/ui/events/ozone/evdev/touch_event_converter_evdev.cc
@@ -186,8 +186,6 @@ events_[i].slot = i; // Dirty the slot so we'll update the consumer at the first opportunity. - // We can't dispatch here as this is currently called on the worker pool. - // TODO(spang): Move initialization off worker pool. events_[i].altered = true; // Optional bits.
diff --git a/ui/events/platform/platform_event_source.cc b/ui/events/platform/platform_event_source.cc index a335626..dfab7fc 100644 --- a/ui/events/platform/platform_event_source.cc +++ b/ui/events/platform/platform_event_source.cc
@@ -75,12 +75,10 @@ if (overridden_dispatcher_) action = overridden_dispatcher_->DispatchEvent(platform_event); - if ((action & POST_DISPATCH_PERFORM_DEFAULT) && - dispatchers_.might_have_observers()) { - base::ObserverList<PlatformEventDispatcher>::Iterator iter(&dispatchers_); - while (PlatformEventDispatcher* dispatcher = iter.GetNext()) { - if (dispatcher->CanDispatchEvent(platform_event)) - action = dispatcher->DispatchEvent(platform_event); + if (action & POST_DISPATCH_PERFORM_DEFAULT) { + for (PlatformEventDispatcher& dispatcher : dispatchers_) { + if (dispatcher.CanDispatchEvent(platform_event)) + action = dispatcher.DispatchEvent(platform_event); if (action & POST_DISPATCH_STOP_PROPAGATION) break; }
diff --git a/ui/events/platform/x11/x11_event_source_libevent.cc b/ui/events/platform/x11/x11_event_source_libevent.cc index 708ab410..c4beb1e4 100644 --- a/ui/events/platform/x11/x11_event_source_libevent.cc +++ b/ui/events/platform/x11/x11_event_source_libevent.cc
@@ -179,12 +179,9 @@ } void X11EventSourceLibevent::DispatchXEventToXEventDispatchers(XEvent* xevent) { - if (dispatchers_xevent_.might_have_observers()) { - base::ObserverList<XEventDispatcher>::Iterator iter(&dispatchers_xevent_); - while (XEventDispatcher* dispatcher = iter.GetNext()) { - if (dispatcher->DispatchXEvent(xevent)) - break; - } + for (XEventDispatcher& dispatcher : dispatchers_xevent_) { + if (dispatcher.DispatchXEvent(xevent)) + break; } }
diff --git a/ui/gfx/buffer_format_util.cc b/ui/gfx/buffer_format_util.cc index 6c70724..931b36d 100644 --- a/ui/gfx/buffer_format_util.cc +++ b/ui/gfx/buffer_format_util.cc
@@ -60,9 +60,10 @@ case BufferFormat::RGBA_4444: case BufferFormat::UYVY_422: checked_size *= 2; + checked_size += 3; if (!checked_size.IsValid()) return false; - *size_in_bytes = checked_size.ValueOrDie(); + *size_in_bytes = checked_size.ValueOrDie() & ~0x3; return true; case BufferFormat::BGRX_8888: case BufferFormat::RGBX_8888:
diff --git a/ui/gl/gl_image_shared_memory_unittest.cc b/ui/gl/gl_image_shared_memory_unittest.cc index f4942f0..3e0a09e 100644 --- a/ui/gl/gl_image_shared_memory_unittest.cc +++ b/ui/gl/gl_image_shared_memory_unittest.cc
@@ -56,6 +56,10 @@ GLImageTestTypes); INSTANTIATE_TYPED_TEST_CASE_P(GLImageSharedMemory, + GLImageOddSizeTest, + GLImageTestTypes); + +INSTANTIATE_TYPED_TEST_CASE_P(GLImageSharedMemory, GLImageCopyTest, GLImageTestTypes);
diff --git a/ui/gl/test/gl_image_test_template.h b/ui/gl/test/gl_image_test_template.h index f12bafb..36dd206 100644 --- a/ui/gl/test/gl_image_test_template.h +++ b/ui/gl/test/gl_image_test_template.h
@@ -215,6 +215,32 @@ REGISTER_TYPED_TEST_CASE_P(GLImageTest, CreateAndDestroy); template <typename GLImageTestDelegate> +class GLImageOddSizeTest : public GLImageTest<GLImageTestDelegate> {}; + +// This test verifies that odd-sized GLImages can be created and destroyed. +TYPED_TEST_CASE_P(GLImageOddSizeTest); + +TYPED_TEST_P(GLImageOddSizeTest, CreateAndDestroy) { + const gfx::Size odd_image_size(17, 53); + const uint8_t* image_color = this->delegate_.GetImageColor(); + + // Create an odd-sized solid color green image of preferred format. This must + // succeed in order for a GLImage to be conformant. + scoped_refptr<GLImage> odd_image = + this->delegate_.CreateSolidColorImage(odd_image_size, image_color); + ASSERT_TRUE(odd_image); + + // Verify that image size is correct. + EXPECT_EQ(odd_image->GetSize().ToString(), odd_image_size.ToString()); + + odd_image->Destroy(true /* have_context */); +} + +// The GLImageTest test case verifies the behaviour that is expected from a +// GLImage in order to be conformant. +REGISTER_TYPED_TEST_CASE_P(GLImageOddSizeTest, CreateAndDestroy); + +template <typename GLImageTestDelegate> class GLImageZeroInitializeTest : public GLImageTest<GLImageTestDelegate> {}; // This test verifies that if an uninitialized image is bound to a texture, the
diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc index 2c26c8f..5db0cdb2 100644 --- a/ui/views/controls/combobox/combobox.cc +++ b/ui/views/controls/combobox/combobox.cc
@@ -37,7 +37,6 @@ #include "ui/views/controls/focus_ring.h" #include "ui/views/controls/focusable_border.h" #include "ui/views/controls/menu/menu_config.h" -#include "ui/views/controls/menu/menu_model_adapter.h" #include "ui/views/controls/menu/menu_runner.h" #include "ui/views/controls/prefix_selector.h" #include "ui/views/controls/textfield/textfield.h" @@ -923,12 +922,10 @@ // Allow |menu_runner_| to be set by the testing API, but if this method is // ever invoked recursively, ensure the old menu is closed. if (!menu_runner_ || menu_runner_->IsRunning()) { - menu_model_adapter_.reset(new MenuModelAdapter( - menu_model_.get(), base::Bind(&Combobox::OnMenuClosed, - base::Unretained(this), original_state))); - menu_runner_.reset( - new MenuRunner(menu_model_adapter_->CreateMenu(), - MenuRunner::COMBOBOX | MenuRunner::ASYNC)); + menu_runner_.reset(new MenuRunner( + menu_model_.get(), MenuRunner::COMBOBOX | MenuRunner::ASYNC, + base::Bind(&Combobox::OnMenuClosed, base::Unretained(this), + original_state))); } menu_runner_->RunMenuAt(GetWidget(), nullptr, bounds, anchor_position, source_type); @@ -936,7 +933,6 @@ void Combobox::OnMenuClosed(Button::ButtonState original_button_state) { menu_runner_.reset(); - menu_model_adapter_.reset(); if (arrow_button_) arrow_button_->SetState(original_button_state); closed_time_ = base::Time::Now();
diff --git a/ui/views/controls/combobox/combobox.h b/ui/views/controls/combobox/combobox.h index 12c0bec..c80623c 100644 --- a/ui/views/controls/combobox/combobox.h +++ b/ui/views/controls/combobox/combobox.h
@@ -28,7 +28,6 @@ class ComboboxListener; class CustomButton; -class MenuModelAdapter; class MenuRunner; class Painter; class PrefixSelector; @@ -211,7 +210,6 @@ // Set while the dropdown is showing. Ensures the menu is closed if |this| is // destroyed. - std::unique_ptr<MenuModelAdapter> menu_model_adapter_; std::unique_ptr<MenuRunner> menu_runner_; // The image to be drawn for this combobox's arrow.
diff --git a/ui/views/controls/menu/menu_runner.cc b/ui/views/controls/menu/menu_runner.cc index bd07a83..3d6f7097 100644 --- a/ui/views/controls/menu/menu_runner.cc +++ b/ui/views/controls/menu/menu_runner.cc
@@ -11,9 +11,14 @@ namespace views { -MenuRunner::MenuRunner(ui::MenuModel* menu_model, int32_t run_types) +MenuRunner::MenuRunner(ui::MenuModel* menu_model, + int32_t run_types, + const base::Closure& on_menu_closed_callback) : run_types_(run_types), - impl_(internal::MenuRunnerImplInterface::Create(menu_model, run_types)) {} + impl_( + internal::MenuRunnerImplInterface::Create(menu_model, + run_types, + on_menu_closed_callback)) {} MenuRunner::MenuRunner(MenuItemView* menu_view, int32_t run_types) : run_types_(run_types), impl_(new internal::MenuRunnerImpl(menu_view)) {}
diff --git a/ui/views/controls/menu/menu_runner.h b/ui/views/controls/menu/menu_runner.h index 1bbc905..3e611f6 100644 --- a/ui/views/controls/menu/menu_runner.h +++ b/ui/views/controls/menu/menu_runner.h
@@ -9,6 +9,7 @@ #include <memory> +#include "base/callback.h" #include "base/compiler_specific.h" #include "base/macros.h" #include "ui/base/ui_base_types.h" @@ -105,9 +106,14 @@ NORMAL_EXIT }; - // Creates a new MenuRunner. - // |run_types| is a bitmask of RunTypes. - MenuRunner(ui::MenuModel* menu_model, int32_t run_types); + // Creates a new MenuRunner, which may use a native menu if available. + // |run_types| is a bitmask of RunTypes. If provided, + // |on_menu_closed_callback| is invoked when the menu is closed. + MenuRunner(ui::MenuModel* menu_model, + int32_t run_types, + const base::Closure& on_menu_closed_callback = base::Closure()); + + // Creates a runner for a custom-created toolkit-views menu. MenuRunner(MenuItemView* menu, int32_t run_types); ~MenuRunner();
diff --git a/ui/views/controls/menu/menu_runner_cocoa_unittest.mm b/ui/views/controls/menu/menu_runner_cocoa_unittest.mm index 924256f..e387dc3 100644 --- a/ui/views/controls/menu/menu_runner_cocoa_unittest.mm +++ b/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
@@ -7,10 +7,14 @@ #import <Cocoa/Cocoa.h> #include "base/macros.h" +#include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/test_timeouts.h" +#include "base/threading/thread_task_runner_handle.h" #import "testing/gtest_mac.h" #include "ui/base/models/simple_menu_model.h" #include "ui/events/event_utils.h" +#include "ui/views/controls/menu/menu_runner_impl_adapter.h" #include "ui/views/test/views_test_base.h" namespace views { @@ -38,7 +42,8 @@ void ExecuteCommand(int command_id, int event_flags) override {} void MenuWillShow(SimpleMenuModel* source) override { - model_->menu_open_callback_.Run(); + if (!model_->menu_open_callback_.is_null()) + model_->menu_open_callback_.Run(); } private: @@ -55,9 +60,16 @@ DISALLOW_COPY_AND_ASSIGN(TestModel); }; +enum class MenuType { NATIVE, VIEWS }; + +std::string MenuTypeToString(::testing::TestParamInfo<MenuType> info) { + return info.param == MenuType::VIEWS ? "VIEWS_MenuItemView" : "NATIVE_NSMenu"; +} + } // namespace -class MenuRunnerCocoaTest : public ViewsTestBase { +class MenuRunnerCocoaTest : public ViewsTestBase, + public ::testing::WithParamInterface<MenuType> { public: enum { kWindowHeight = 200, @@ -80,7 +92,12 @@ gfx::Rect(kWindowOffset, kWindowOffset, kWindowWidth, kWindowHeight)); parent_->Show(); - runner_ = new internal::MenuRunnerImplCocoa(menu_.get()); + base::Closure on_close = base::Bind(&MenuRunnerCocoaTest::MenuCloseCallback, + base::Unretained(this)); + if (GetParam() == MenuType::NATIVE) + runner_ = new internal::MenuRunnerImplCocoa(menu_.get(), on_close); + else + runner_ = new internal::MenuRunnerImplAdapter(menu_.get(), on_close); EXPECT_FALSE(runner_->IsRunning()); } @@ -94,13 +111,25 @@ ViewsTestBase::TearDown(); } + int IsAsync() const { return GetParam() == MenuType::VIEWS; } + // Runs the menu after registering |callback| as the menu open callback. MenuRunner::RunResult RunMenu(const base::Closure& callback) { - menu_->set_menu_open_callback( - base::Bind(&MenuRunnerCocoaTest::RunMenuWrapperCallback, - base::Unretained(this), callback)); - return runner_->RunMenuAt(parent_, nullptr, gfx::Rect(), - MENU_ANCHOR_TOPLEFT, MenuRunner::CONTEXT_MENU); + if (IsAsync()) { + // Cancelling an async menu under MenuController::OpenMenuImpl() (which + // invokes WillShowMenu()) will cause a UAF when that same function tries + // to show the menu. So post a task instead. + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback); + } else { + menu_->set_menu_open_callback( + base::Bind(&MenuRunnerCocoaTest::RunMenuWrapperCallback, + base::Unretained(this), callback)); + } + + // Always pass ASYNC, even though native menus will be sync. + int run_types = MenuRunner::CONTEXT_MENU | MenuRunner::ASYNC; + return MaybeRunAsync(runner_->RunMenuAt(parent_, nullptr, gfx::Rect(), + MENU_ANCHOR_TOPLEFT, run_types)); } // Runs then cancels a combobox menu and captures the frame of the anchoring @@ -112,11 +141,17 @@ // go up by one (the anchor view) while the menu is shown. EXPECT_EQ(1u, [[parent_->GetNativeView() subviews] count]); - menu_->set_menu_open_callback(base::Bind( - &MenuRunnerCocoaTest::RunMenuAtCallback, base::Unretained(this))); + base::Closure callback = + base::Bind(&MenuRunnerCocoaTest::ComboboxRunMenuAtCallback, + base::Unretained(this)); + if (IsAsync()) + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback); + else + menu_->set_menu_open_callback(callback); - MenuRunner::RunResult result = runner_->RunMenuAt( - parent_, nullptr, anchor, MENU_ANCHOR_TOPLEFT, MenuRunner::COMBOBOX); + MenuRunner::RunResult result = MaybeRunAsync( + runner_->RunMenuAt(parent_, nullptr, anchor, MENU_ANCHOR_TOPLEFT, + MenuRunner::COMBOBOX | MenuRunner::ASYNC)); // Ensure the anchor view is removed. EXPECT_EQ(1u, [[parent_->GetNativeView() subviews] count]); @@ -125,15 +160,24 @@ void MenuCancelCallback() { runner_->Cancel(); - // For a syncronous menu, MenuRunner::IsRunning() should return true - // immediately after MenuRunner::Cancel() since the menu message loop has - // not yet terminated. It has only been marked for termination. - EXPECT_TRUE(runner_->IsRunning()); + if (IsAsync()) { + // Async menus report their cancellation immediately. + EXPECT_FALSE(runner_->IsRunning()); + } else { + // For a synchronous menu, MenuRunner::IsRunning() should return true + // immediately after MenuRunner::Cancel() since the menu message loop has + // not yet terminated. It has only been marked for termination. + EXPECT_TRUE(runner_->IsRunning()); + } } void MenuDeleteCallback() { runner_->Release(); runner_ = nullptr; + // Deleting an async menu intentionally does not invoke MenuCloseCallback(). + // (The callback is typically a method on something in the process of being + // destroyed). So invoke QuitAsyncRunLoop() here as well. + QuitAsyncRunLoop(); } void MenuCancelAndDeleteCallback() { @@ -144,9 +188,10 @@ protected: std::unique_ptr<TestModel> menu_; - internal::MenuRunnerImplCocoa* runner_ = nullptr; + internal::MenuRunnerImplInterface* runner_ = nullptr; views::Widget* parent_ = nullptr; NSRect last_anchor_frame_ = NSZeroRect; + int menu_close_count_ = 0; private: void RunMenuWrapperCallback(const base::Closure& callback) { @@ -154,70 +199,139 @@ callback.Run(); } - void RunMenuAtCallback() { + void ComboboxRunMenuAtCallback() { NSArray* subviews = [parent_->GetNativeView() subviews]; - EXPECT_EQ(2u, [subviews count]); - last_anchor_frame_ = [[subviews objectAtIndex:1] frame]; + // An anchor view should only be added for Native menus. + if (GetParam() == MenuType::NATIVE) { + ASSERT_EQ(2u, [subviews count]); + last_anchor_frame_ = [[subviews objectAtIndex:1] frame]; + } else { + EXPECT_EQ(1u, [subviews count]); + } runner_->Cancel(); } + // Run a nested message loop so that async and sync menus can be tested the + // same way. + MenuRunner::RunResult MaybeRunAsync(MenuRunner::RunResult run_result) { + if (!IsAsync()) + return run_result; + + // Async menus should always return NORMAL_EXIT. + EXPECT_EQ(MenuRunner::NORMAL_EXIT, run_result); + base::RunLoop run_loop; + quit_closure_ = run_loop.QuitClosure(); + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, quit_closure_, TestTimeouts::action_timeout()); + run_loop.Run(); + + // |quit_closure_| should be run by QuitAsyncRunLoop(), not the timeout. + EXPECT_TRUE(quit_closure_.is_null()); + return run_result; + } + + void QuitAsyncRunLoop() { + if (!IsAsync()) { + EXPECT_TRUE(quit_closure_.is_null()); + return; + } + ASSERT_FALSE(quit_closure_.is_null()); + quit_closure_.Run(); + quit_closure_.Reset(); + } + + void MenuCloseCallback() { + ++menu_close_count_; + QuitAsyncRunLoop(); + } + + base::Closure quit_closure_; + DISALLOW_COPY_AND_ASSIGN(MenuRunnerCocoaTest); }; -TEST_F(MenuRunnerCocoaTest, RunMenuAndCancel) { +TEST_P(MenuRunnerCocoaTest, RunMenuAndCancel) { base::TimeTicks min_time = ui::EventTimeForNow(); MenuRunner::RunResult result = RunMenu(base::Bind( &MenuRunnerCocoaTest::MenuCancelCallback, base::Unretained(this))); + EXPECT_EQ(1, menu_close_count_); EXPECT_EQ(MenuRunner::NORMAL_EXIT, result); EXPECT_FALSE(runner_->IsRunning()); - EXPECT_GE(runner_->GetClosingEventTime(), min_time); + if (GetParam() == MenuType::VIEWS) { + // MenuItemView's MenuRunnerImpl gets the closing time from MenuController:: + // closing_event_time(). This is is reset on show, but only updated when an + // event closes the menu -- not a cancellation. + EXPECT_EQ(runner_->GetClosingEventTime(), base::TimeTicks()); + } else { + EXPECT_GE(runner_->GetClosingEventTime(), min_time); + } EXPECT_LE(runner_->GetClosingEventTime(), ui::EventTimeForNow()); // Cancel again. runner_->Cancel(); EXPECT_FALSE(runner_->IsRunning()); + EXPECT_EQ(1, menu_close_count_); } -TEST_F(MenuRunnerCocoaTest, RunMenuAndDelete) { +TEST_P(MenuRunnerCocoaTest, RunMenuAndDelete) { MenuRunner::RunResult result = RunMenu(base::Bind( &MenuRunnerCocoaTest::MenuDeleteCallback, base::Unretained(this))); - EXPECT_EQ(MenuRunner::MENU_DELETED, result); + // Note the close callback is NOT invoked for deleted menus. + EXPECT_EQ(0, menu_close_count_); + + // Async menus always return NORMAL from RunMenuAt(). + if (GetParam() == MenuType::VIEWS) + EXPECT_EQ(MenuRunner::NORMAL_EXIT, result); + else + EXPECT_EQ(MenuRunner::MENU_DELETED, result); } // Ensure a menu can be safely released immediately after a call to Cancel() in // the same run loop iteration. -TEST_F(MenuRunnerCocoaTest, DestroyAfterCanceling) { +TEST_P(MenuRunnerCocoaTest, DestroyAfterCanceling) { MenuRunner::RunResult result = RunMenu(base::Bind(&MenuRunnerCocoaTest::MenuCancelAndDeleteCallback, base::Unretained(this))); - EXPECT_EQ(MenuRunner::MENU_DELETED, result); + + if (IsAsync()) { + EXPECT_EQ(MenuRunner::NORMAL_EXIT, result); + EXPECT_EQ(1, menu_close_count_); + } else { + EXPECT_EQ(MenuRunner::MENU_DELETED, result); + // For a synchronous menu, the deletion happens before the cancel can be + // processed, so the close callback will not be invoked. + EXPECT_EQ(0, menu_close_count_); + } } -TEST_F(MenuRunnerCocoaTest, RunMenuTwice) { +TEST_P(MenuRunnerCocoaTest, RunMenuTwice) { for (int i = 0; i < 2; ++i) { MenuRunner::RunResult result = RunMenu(base::Bind( &MenuRunnerCocoaTest::MenuCancelCallback, base::Unretained(this))); EXPECT_EQ(MenuRunner::NORMAL_EXIT, result); EXPECT_FALSE(runner_->IsRunning()); + EXPECT_EQ(i + 1, menu_close_count_); } } -TEST_F(MenuRunnerCocoaTest, CancelWithoutRunning) { +TEST_P(MenuRunnerCocoaTest, CancelWithoutRunning) { runner_->Cancel(); EXPECT_FALSE(runner_->IsRunning()); EXPECT_EQ(base::TimeTicks(), runner_->GetClosingEventTime()); + EXPECT_EQ(0, menu_close_count_); } -TEST_F(MenuRunnerCocoaTest, DeleteWithoutRunning) { +TEST_P(MenuRunnerCocoaTest, DeleteWithoutRunning) { runner_->Release(); runner_ = NULL; + EXPECT_EQ(0, menu_close_count_); } // Tests anchoring of the menus used for toolkit-views Comboboxes. -TEST_F(MenuRunnerCocoaTest, ComboboxAnchoring) { +TEST_P(MenuRunnerCocoaTest, ComboboxAnchoring) { // Combobox at 20,10 in the Widget. const gfx::Rect combobox_rect(20, 10, 80, 50); @@ -227,6 +341,12 @@ anchor_rect.Offset(kWindowOffset, kWindowOffset); RunMenuAt(anchor_rect); + if (GetParam() != MenuType::NATIVE) { + // Combobox anchoring is only implemented for native menus. + EXPECT_NSEQ(NSZeroRect, last_anchor_frame_); + return; + } + // Nothing is checked, so the anchor view should have no height, to ensure the // menu goes below the anchor rect. There should also be no x-offset since the // there is no need to line-up text. @@ -258,5 +378,10 @@ EXPECT_EQ(combobox_rect.right(), last_anchor_frame_.origin.x); } +INSTANTIATE_TEST_CASE_P(, + MenuRunnerCocoaTest, + ::testing::Values(MenuType::NATIVE, MenuType::VIEWS), + &MenuTypeToString); + } // namespace test } // namespace views
diff --git a/ui/views/controls/menu/menu_runner_impl.cc b/ui/views/controls/menu/menu_runner_impl.cc index ba9078f..9061663 100644 --- a/ui/views/controls/menu/menu_runner_impl.cc +++ b/ui/views/controls/menu/menu_runner_impl.cc
@@ -23,8 +23,9 @@ #if !defined(OS_MACOSX) MenuRunnerImplInterface* MenuRunnerImplInterface::Create( ui::MenuModel* menu_model, - int32_t run_types) { - return new MenuRunnerImplAdapter(menu_model); + int32_t run_types, + const base::Closure& on_menu_closed_callback) { + return new MenuRunnerImplAdapter(menu_model, on_menu_closed_callback); } #endif
diff --git a/ui/views/controls/menu/menu_runner_impl_adapter.cc b/ui/views/controls/menu/menu_runner_impl_adapter.cc index 932af7ec..31241bfa 100644 --- a/ui/views/controls/menu/menu_runner_impl_adapter.cc +++ b/ui/views/controls/menu/menu_runner_impl_adapter.cc
@@ -10,10 +10,12 @@ namespace views { namespace internal { -MenuRunnerImplAdapter::MenuRunnerImplAdapter(ui::MenuModel* menu_model) - : menu_model_adapter_(new MenuModelAdapter(menu_model)), - impl_(new MenuRunnerImpl(menu_model_adapter_->CreateMenu())) { -} +MenuRunnerImplAdapter::MenuRunnerImplAdapter( + ui::MenuModel* menu_model, + const base::Closure& on_menu_done_callback) + : menu_model_adapter_( + new MenuModelAdapter(menu_model, on_menu_done_callback)), + impl_(new MenuRunnerImpl(menu_model_adapter_->CreateMenu())) {} bool MenuRunnerImplAdapter::IsRunning() const { return impl_->IsRunning();
diff --git a/ui/views/controls/menu/menu_runner_impl_adapter.h b/ui/views/controls/menu/menu_runner_impl_adapter.h index 9d4fcec..09569e4 100644 --- a/ui/views/controls/menu/menu_runner_impl_adapter.h +++ b/ui/views/controls/menu/menu_runner_impl_adapter.h
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "ui/views/controls/menu/menu_runner_impl_interface.h" +#include "ui/views/views_export.h" namespace views { namespace internal { @@ -16,9 +17,11 @@ class MenuRunnerImpl; // Given a MenuModel, adapts MenuRunnerImpl which expects a MenuItemView. -class MenuRunnerImplAdapter : public MenuRunnerImplInterface { +class VIEWS_EXPORT MenuRunnerImplAdapter + : public NON_EXPORTED_BASE(MenuRunnerImplInterface) { public: - explicit MenuRunnerImplAdapter(ui::MenuModel* menu_model); + MenuRunnerImplAdapter(ui::MenuModel* menu_model, + const base::Closure& on_menu_closed_callback); // MenuRunnerImplInterface: bool IsRunning() const override;
diff --git a/ui/views/controls/menu/menu_runner_impl_cocoa.h b/ui/views/controls/menu/menu_runner_impl_cocoa.h index bb5f4b86..4b4184c 100644 --- a/ui/views/controls/menu/menu_runner_impl_cocoa.h +++ b/ui/views/controls/menu/menu_runner_impl_cocoa.h
@@ -5,13 +5,13 @@ #ifndef UI_VIEWS_CONTROLS_MENU_MENU_RUNNER_IMPL_COCOA_H_ #define UI_VIEWS_CONTROLS_MENU_MENU_RUNNER_IMPL_COCOA_H_ -#include "ui/views/controls/menu/menu_runner_impl_interface.h" - #include <stdint.h> +#include "base/callback.h" #import "base/mac/scoped_nsobject.h" #include "base/macros.h" #include "base/time/time.h" +#include "ui/views/controls/menu/menu_runner_impl_interface.h" @class MenuController; @@ -21,7 +21,8 @@ // A menu runner implementation that uses NSMenu to show a context menu. class VIEWS_EXPORT MenuRunnerImplCocoa : public MenuRunnerImplInterface { public: - explicit MenuRunnerImplCocoa(ui::MenuModel* menu); + MenuRunnerImplCocoa(ui::MenuModel* menu, + const base::Closure& on_menu_closed_callback); bool IsRunning() const override; void Release() override; @@ -48,6 +49,9 @@ // The timestamp of the event which closed the menu - or 0. base::TimeTicks closing_event_time_; + // Invoked before RunMenuAt() returns, except upon a Release(). + base::Closure on_menu_closed_callback_; + DISALLOW_COPY_AND_ASSIGN(MenuRunnerImplCocoa); };
diff --git a/ui/views/controls/menu/menu_runner_impl_cocoa.mm b/ui/views/controls/menu/menu_runner_impl_cocoa.mm index f04c2eb2..f4ac01b 100644 --- a/ui/views/controls/menu/menu_runner_impl_cocoa.mm +++ b/ui/views/controls/menu/menu_runner_impl_cocoa.mm
@@ -84,19 +84,23 @@ // static MenuRunnerImplInterface* MenuRunnerImplInterface::Create( ui::MenuModel* menu_model, - int32_t run_types) { + int32_t run_types, + const base::Closure& on_menu_closed_callback) { if ((run_types & kNativeRunTypes) != 0 && (run_types & MenuRunner::IS_NESTED) == 0) { - return new MenuRunnerImplCocoa(menu_model); + return new MenuRunnerImplCocoa(menu_model, on_menu_closed_callback); } - return new MenuRunnerImplAdapter(menu_model); + return new MenuRunnerImplAdapter(menu_model, on_menu_closed_callback); } -MenuRunnerImplCocoa::MenuRunnerImplCocoa(ui::MenuModel* menu) +MenuRunnerImplCocoa::MenuRunnerImplCocoa( + ui::MenuModel* menu, + const base::Closure& on_menu_closed_callback) : running_(false), delete_after_run_(false), - closing_event_time_(base::TimeTicks()) { + closing_event_time_(base::TimeTicks()), + on_menu_closed_callback_(on_menu_closed_callback) { menu_controller_.reset( [[MenuController alloc] initWithModel:menu useWithPopUpButtonCell:NO]); } @@ -154,6 +158,11 @@ return MenuRunner::MENU_DELETED; } + // Don't invoke the callback if Release() was called, since that usually means + // the owning instance is being destroyed. + if (!on_menu_closed_callback_.is_null()) + on_menu_closed_callback_.Run(); + return MenuRunner::NORMAL_EXIT; }
diff --git a/ui/views/controls/menu/menu_runner_impl_interface.h b/ui/views/controls/menu/menu_runner_impl_interface.h index 3aad7e3..1e7e45f6 100644 --- a/ui/views/controls/menu/menu_runner_impl_interface.h +++ b/ui/views/controls/menu/menu_runner_impl_interface.h
@@ -7,6 +7,7 @@ #include <stdint.h> +#include "base/callback_forward.h" #include "ui/views/controls/menu/menu_runner.h" namespace views { @@ -23,8 +24,10 @@ public: // Creates a concrete instance for running |menu_model|. // |run_types| is a bitmask of MenuRunner::RunTypes. - static MenuRunnerImplInterface* Create(ui::MenuModel* menu_model, - int32_t run_types); + static MenuRunnerImplInterface* Create( + ui::MenuModel* menu_model, + int32_t run_types, + const base::Closure& on_menu_closed_callback); // Returns true if we're in a nested message loop running the menu. virtual bool IsRunning() const = 0;
diff --git a/ui/views/controls/tabbed_pane/OWNERS b/ui/views/controls/tabbed_pane/OWNERS new file mode 100644 index 0000000..80d20216 --- /dev/null +++ b/ui/views/controls/tabbed_pane/OWNERS
@@ -0,0 +1,2 @@ +ellyjones@chromium.org +msw@chromium.org
diff --git a/ui/views/controls/tabbed_pane/tabbed_pane.cc b/ui/views/controls/tabbed_pane/tabbed_pane.cc index 56415db..02da2f9 100644 --- a/ui/views/controls/tabbed_pane/tabbed_pane.cc +++ b/ui/views/controls/tabbed_pane/tabbed_pane.cc
@@ -13,6 +13,9 @@ #include "ui/base/material_design/material_design_controller.h" #include "ui/base/resource/resource_bundle.h" #include "ui/events/keycodes/keyboard_codes.h" +#include "ui/gfx/animation/animation_delegate.h" +#include "ui/gfx/animation/linear_animation.h" +#include "ui/gfx/animation/tween.h" #include "ui/gfx/canvas.h" #include "ui/gfx/font_list.h" #include "ui/native_theme/native_theme.h" @@ -58,7 +61,8 @@ // Overridden from View: gfx::Size GetPreferredSize() const override; - void OnPaintBorder(gfx::Canvas* canvas) override; + void OnFocus() override; + void OnBlur() override; private: DISALLOW_COPY_AND_ASSIGN(MdTab); @@ -73,6 +77,11 @@ TabStrip(); ~TabStrip() override; + // Called by TabStrip when the selected tab changes. This function is only + // called if |from_tab| is not null, i.e., there was a previously selected + // tab. + virtual void OnSelectedTabChanged(Tab* from_tab, Tab* to_tab); + // Overridden from View: const char* GetClassName() const override; void OnPaintBorder(gfx::Canvas* canvas) override; @@ -88,15 +97,34 @@ // A subclass of TabStrip that implements the Harmony visual styling. This // class uses a BoxLayout to position tabs. -class MdTabStrip : public TabStrip { +class MdTabStrip : public TabStrip, public gfx::AnimationDelegate { public: MdTabStrip(); ~MdTabStrip() override; + // Overridden from TabStrip: + void OnSelectedTabChanged(Tab* from_tab, Tab* to_tab) override; + // Overridden from View: void OnPaintBorder(gfx::Canvas* canvas) override; + // Overridden from AnimationDelegate: + void AnimationProgressed(const gfx::Animation* animation) override; + void AnimationEnded(const gfx::Animation* animation) override; + private: + // Animations for expanding and contracting the selection bar. When changing + // selections, the selection bar first grows to encompass both the old and new + // selections, then shrinks to encompass only the new selection. The rates of + // expansion and contraction each follow the cubic bezier curves used in + // gfx::Tween; see MdTabStrip::OnPaintBorder for details. + std::unique_ptr<gfx::LinearAnimation> expand_animation_; + std::unique_ptr<gfx::LinearAnimation> contract_animation_; + + // The x-coordinate ranges of the old selection and the new selection. + gfx::Range animating_from_; + gfx::Range animating_to_; + DISALLOW_COPY_AND_ASSIGN(MdTabStrip); }; @@ -238,6 +266,8 @@ const base::string16& title, View* contents) : Tab(tabbed_pane, title, contents) { + const int kBorderThickness = 2; + SetBorder(Border::CreateEmptyBorder(gfx::Insets(kBorderThickness))); OnStateChanged(); } @@ -262,44 +292,24 @@ gfx::Font::NORMAL, font_weight)); } -void MdTab::OnPaintBorder(gfx::Canvas* canvas) { - const int kBorderStrokeWidth = 2; - if (!HasFocus()) { - SkColor color = GetNativeTheme()->GetSystemColor( - selected() ? ui::NativeTheme::kColorId_FocusedBorderColor - : ui::NativeTheme::kColorId_UnfocusedBorderColor); - int thickness = selected() ? kBorderStrokeWidth : kBorderStrokeWidth / 2; - canvas->FillRect(gfx::Rect(0, height() - thickness, width(), thickness), - color); - return; - } - - // TODO(ellyjones): should this 0x66 be part of NativeTheme somehow? - SkColor base_color = GetNativeTheme()->GetSystemColor( - ui::NativeTheme::kColorId_FocusedBorderColor); - SkColor light_color = SkColorSetA(base_color, 0x66); - - SkPaint paint; - paint.setColor(light_color); - paint.setStyle(SkPaint::kStroke_Style); - paint.setStrokeWidth(kBorderStrokeWidth); - - gfx::RectF bounds = gfx::RectF(GetLocalBounds()); - bounds.Inset(gfx::Insets(kBorderStrokeWidth / 2.f)); - - // Draw the lighter-colored stroke first, then draw the heavier stroke over - // the bottom of it. This is fine because the heavier stroke has 1.0 alpha, so - // the lighter stroke won't show through. - canvas->DrawRect(bounds, paint); - canvas->FillRect( - gfx::Rect(0, height() - kBorderStrokeWidth, width(), kBorderStrokeWidth), - base_color); -} - gfx::Size MdTab::GetPreferredSize() const { return gfx::Size(Tab::GetPreferredSize().width(), kHarmonyTabStripTabHeight); } +void MdTab::OnFocus() { + SetBorder(Border::CreateSolidBorder( + GetInsets().top(), + SkColorSetA(GetNativeTheme()->GetSystemColor( + ui::NativeTheme::kColorId_FocusedBorderColor), + 0x66))); + SchedulePaint(); +} + +void MdTab::OnBlur() { + SetBorder(Border::CreateEmptyBorder(GetInsets())); + SchedulePaint(); +} + // static const char TabStrip::kViewClassName[] = "TabStrip"; @@ -315,6 +325,8 @@ TabStrip::~TabStrip() {} +void TabStrip::OnSelectedTabChanged(Tab* from_tab, Tab* to_tab) {} + const char* TabStrip::GetClassName() const { return kViewClassName; } @@ -381,12 +393,108 @@ layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH); layout->SetDefaultFlex(1); SetLayoutManager(layout); + + // These durations are taken from the Paper Tabs source: + // https://github.com/PolymerElements/paper-tabs/blob/master/paper-tabs.html + // See |selectionBar.expand| and |selectionBar.contract|. + const int kExpandAnimationDurationMs = 150; + expand_animation_.reset(new gfx::LinearAnimation(this)); + expand_animation_->SetDuration(kExpandAnimationDurationMs); + + const int kContractAnimationDurationMs = 180; + contract_animation_.reset(new gfx::LinearAnimation(this)); + contract_animation_->SetDuration(kContractAnimationDurationMs); } MdTabStrip::~MdTabStrip() {} -// The tab strip "border" is drawn as part of the tabs. -void MdTabStrip::OnPaintBorder(gfx::Canvas* canvas) {} +void MdTabStrip::OnSelectedTabChanged(Tab* from_tab, Tab* to_tab) { + DCHECK(!from_tab->selected()); + DCHECK(to_tab->selected()); + + animating_from_ = + gfx::Range(from_tab->x(), from_tab->x() + from_tab->width()); + animating_to_ = gfx::Range(to_tab->x(), to_tab->x() + to_tab->width()); + + contract_animation_->Stop(); + expand_animation_->Start(); +} + +void MdTabStrip::OnPaintBorder(gfx::Canvas* canvas) { + int max_y = child_at(0)->y() + child_at(0)->height(); + const int kUnselectedBorderThickness = 1; + const int kSelectedBorderThickness = 2; + + // First, draw the unselected border across the TabStrip's entire width. The + // area underneath the selected tab will be overdrawn later. + canvas->FillRect(gfx::Rect(0, max_y - kUnselectedBorderThickness, width(), + kUnselectedBorderThickness), + GetNativeTheme()->GetSystemColor( + ui::NativeTheme::kColorId_UnfocusedBorderColor)); + + int min_x = 0; + int max_x = 0; + + // Now, figure out the range to draw the selection marker underneath. There + // are three states here: + // 1) Expand animation is running: use FAST_OUT_LINEAR_IN to grow the + // selection marker until it encompasses both the previously selected tab + // and the currently selected tab; + // 2) Contract animation is running: use LINEAR_OUT_SLOW_IN to shrink the + // selection marker until it encompasses only the currently selected tab; + // 3) No animations running: the selection marker is only under the currently + // selected tab. + Tab* tab = GetSelectedTab(); + if (!tab) + return; + if (expand_animation_->is_animating()) { + bool animating_left = animating_to_.start() < animating_from_.start(); + double anim_value = gfx::Tween::CalculateValue( + gfx::Tween::FAST_OUT_LINEAR_IN, expand_animation_->GetCurrentValue()); + + if (animating_left) { + min_x = gfx::Tween::IntValueBetween(anim_value, animating_from_.start(), + animating_to_.start()); + max_x = animating_from_.end(); + } else { + min_x = animating_from_.start(); + max_x = gfx::Tween::IntValueBetween(anim_value, animating_from_.end(), + animating_to_.end()); + } + } else if (contract_animation_->is_animating()) { + bool animating_left = animating_to_.start() < animating_from_.start(); + double anim_value = gfx::Tween::CalculateValue( + gfx::Tween::LINEAR_OUT_SLOW_IN, contract_animation_->GetCurrentValue()); + if (animating_left) { + min_x = animating_to_.start(); + max_x = gfx::Tween::IntValueBetween(anim_value, animating_from_.end(), + animating_to_.end()); + } else { + min_x = gfx::Tween::IntValueBetween(anim_value, animating_from_.start(), + animating_to_.start()); + max_x = animating_to_.end(); + } + } else if (tab) { + min_x = tab->x(); + max_x = tab->x() + tab->width(); + } + + DCHECK(min_x != max_x); + // Draw over the unselected border from above. + canvas->FillRect(gfx::Rect(min_x, max_y - kSelectedBorderThickness, + max_x - min_x, kSelectedBorderThickness), + GetNativeTheme()->GetSystemColor( + ui::NativeTheme::kColorId_FocusedBorderColor)); +} + +void MdTabStrip::AnimationProgressed(const gfx::Animation* animation) { + SchedulePaint(); +} + +void MdTabStrip::AnimationEnded(const gfx::Animation* animation) { + if (animation == expand_animation_.get()) + contract_animation_->Start(); +} TabbedPane::TabbedPane() : listener_(NULL), @@ -441,6 +549,7 @@ if (old_selected_tab->HasFocus()) new_selected_tab->RequestFocus(); old_selected_tab->SetSelected(false); + tab_strip_->OnSelectedTabChanged(old_selected_tab, new_selected_tab); } tab_strip_->SchedulePaint();
diff --git a/ui/views/mus/pointer_watcher_event_router.cc b/ui/views/mus/pointer_watcher_event_router.cc index 998c4cf0..6d0217b 100644 --- a/ui/views/mus/pointer_watcher_event_router.cc +++ b/ui/views/mus/pointer_watcher_event_router.cc
@@ -17,14 +17,7 @@ bool HasPointerWatcher( base::ObserverList<views::PointerWatcher, true>* observer_list) { - if (!observer_list->might_have_observers()) - return false; - - // might_have_observers() returned true, see if there really are any - // observers. The only way to truly know is to use an Iterator and see if it - // has at least one observer. - base::ObserverList<PointerWatcher>::Iterator iterator(observer_list); - return !!iterator.GetNext(); + return observer_list->begin() != observer_list->end(); } } // namespace
diff --git a/ui/webui/resources/css/roboto.css b/ui/webui/resources/css/roboto.css index 00cbd32a..af0bdbc 100644 --- a/ui/webui/resources/css/roboto.css +++ b/ui/webui/resources/css/roboto.css
@@ -2,7 +2,7 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -<if expr="not chromeos"> +<if expr="not chromeos and not is_android"> @font-face { font-family: 'Roboto'; font-style: normal;
diff --git a/ui/webui/resources/webui_resources.grd b/ui/webui/resources/webui_resources.grd index 16c90e21..1753e0b08 100644 --- a/ui/webui/resources/webui_resources.grd +++ b/ui/webui/resources/webui_resources.grd
@@ -19,7 +19,7 @@ <!-- Roboto Font. Roboto-Regular and Roboto-Light is already available on Android, and Roboto-Medium is not used on Android. All 6 weights of Roboto are available on Chrome OS.--> - <if expr="not android and not chromeos"> + <if expr="not is_android and not chromeos"> <include name="IDR_WEBUI_ROBOTO_ROBOTO_REGULAR_WOFF2" file="roboto/roboto-regular.woff2" type="BINDATA" /> <include name="IDR_WEBUI_ROBOTO_ROBOTO_MEDIUM_WOFF2" file="roboto/roboto-medium.woff2" type="BINDATA" /> <include name="IDR_WEBUI_ROBOTO_ROBOTO_BOLD_WOFF2" file="roboto/roboto-bold.woff2" type="BINDATA" />
diff --git a/ui/wm/core/compound_event_filter.cc b/ui/wm/core/compound_event_filter.cc index 0e65525..d487b1a 100644 --- a/ui/wm/core/compound_event_filter.cc +++ b/ui/wm/core/compound_event_filter.cc
@@ -129,29 +129,26 @@ } void CompoundEventFilter::FilterKeyEvent(ui::KeyEvent* event) { - if (handlers_.might_have_observers()) { - base::ObserverListBase<ui::EventHandler>::Iterator it(&handlers_); - ui::EventHandler* handler; - while (!event->stopped_propagation() && (handler = it.GetNext()) != NULL) - handler->OnKeyEvent(event); + for (ui::EventHandler& handler : handlers_) { + if (event->stopped_propagation()) + break; + handler.OnKeyEvent(event); } } void CompoundEventFilter::FilterMouseEvent(ui::MouseEvent* event) { - if (handlers_.might_have_observers()) { - base::ObserverListBase<ui::EventHandler>::Iterator it(&handlers_); - ui::EventHandler* handler; - while (!event->stopped_propagation() && (handler = it.GetNext()) != NULL) - handler->OnMouseEvent(event); + for (ui::EventHandler& handler : handlers_) { + if (event->stopped_propagation()) + break; + handler.OnMouseEvent(event); } } void CompoundEventFilter::FilterTouchEvent(ui::TouchEvent* event) { - if (handlers_.might_have_observers()) { - base::ObserverListBase<ui::EventHandler>::Iterator it(&handlers_); - ui::EventHandler* handler; - while (!event->stopped_propagation() && (handler = it.GetNext()) != NULL) - handler->OnTouchEvent(event); + for (ui::EventHandler& handler : handlers_) { + if (event->stopped_propagation()) + break; + handler.OnTouchEvent(event); } } @@ -240,11 +237,10 @@ } void CompoundEventFilter::OnGestureEvent(ui::GestureEvent* event) { - if (handlers_.might_have_observers()) { - base::ObserverListBase<ui::EventHandler>::Iterator it(&handlers_); - ui::EventHandler* handler; - while (!event->stopped_propagation() && (handler = it.GetNext()) != NULL) - handler->OnGestureEvent(event); + for (ui::EventHandler& handler : handlers_) { + if (event->stopped_propagation()) + break; + handler.OnGestureEvent(event); } }