diff --git a/DEPS b/DEPS index 090f44c..8c15a55c 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,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': 'd689f7a5313a7fd501c2572c493fe6d91a88cba4', + 'skia_revision': 'c86b1456f73eaf5a43fac8c920c7140993b2f0ba', # 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': '85cebb78ba98bc5fc7ffb7c7a78521b4441df05b', + 'v8_revision': '7fbbaba59ab53ff73965c0c71584cb467bd7b390', # 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. @@ -232,7 +232,7 @@ Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067', 'src/third_party/webrtc': - Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '8ff7cecc5bc21065d2ca7ae4b65a2f28887466e0', # commit position 16354 + Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '2a4b1756ee43486e2bf1e0194a2d5850ce2ae050', # commit position 16404 'src/third_party/openmax_dl': Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' + Var('openmax_dl_revision'),
diff --git a/ash/common/shelf/shelf_layout_manager.cc b/ash/common/shelf/shelf_layout_manager.cc index d51f088..1639fba 100644 --- a/ash/common/shelf/shelf_layout_manager.cc +++ b/ash/common/shelf/shelf_layout_manager.cc
@@ -9,6 +9,7 @@ #include <vector> #include "ash/common/material_design/material_design_controller.h" +#include "ash/common/session/session_controller.h" #include "ash/common/session/session_state_delegate.h" #include "ash/common/shelf/shelf_constants.h" #include "ash/common/shelf/shelf_layout_manager_observer.h" @@ -95,7 +96,7 @@ void OnImplicitAnimationsCompleted() override { if (shelf_) - shelf_->UpdateShelfBackground(BACKGROUND_CHANGE_ANIMATE); + shelf_->MaybeUpdateShelfBackground(BACKGROUND_CHANGE_ANIMATE); delete this; } @@ -111,6 +112,31 @@ DISALLOW_COPY_AND_ASSIGN(UpdateShelfObserver); }; +ShelfLayoutManager::State::State() + : visibility_state(SHELF_VISIBLE), + auto_hide_state(SHELF_AUTO_HIDE_HIDDEN), + window_state(wm::WORKSPACE_WINDOW_STATE_DEFAULT), + pre_lock_screen_animation_active(false), + session_state(session_manager::SessionState::UNKNOWN) {} + +bool ShelfLayoutManager::State::IsAddingSecondaryUser() const { + return session_state == session_manager::SessionState::LOGIN_SECONDARY; +} + +bool ShelfLayoutManager::State::IsScreenLocked() const { + return session_state == session_manager::SessionState::LOCKED; +} + +bool ShelfLayoutManager::State::Equals(const State& other) const { + return other.visibility_state == visibility_state && + (visibility_state != SHELF_AUTO_HIDE || + other.auto_hide_state == auto_hide_state) && + other.window_state == window_state && + other.pre_lock_screen_animation_active == + pre_lock_screen_animation_active && + other.session_state == session_state; +} + // ShelfLayoutManager ---------------------------------------------------------- ShelfLayoutManager::ShelfLayoutManager(ShelfWidget* shelf_widget, @@ -125,13 +151,16 @@ gesture_drag_auto_hide_state_(SHELF_AUTO_HIDE_SHOWN), update_shelf_observer_(NULL), chromevox_panel_height_(0), - duration_override_in_ms_(0) { + duration_override_in_ms_(0), + shelf_background_type_(SHELF_BACKGROUND_OVERLAP) { DCHECK(shelf_widget_); DCHECK(wm_shelf_); WmShell::Get()->AddShellObserver(this); WmShell::Get()->AddLockStateObserver(this); WmShell::Get()->AddActivationObserver(this); - WmShell::Get()->GetSessionStateDelegate()->AddSessionStateObserver(this); + WmShell::Get()->session_controller()->AddSessionStateObserver(this); + state_.session_state = + WmShell::Get()->session_controller()->GetSessionState(); } ShelfLayoutManager::~ShelfLayoutManager() { @@ -142,7 +171,7 @@ observer.WillDeleteShelfLayoutManager(); WmShell::Get()->RemoveShellObserver(this); WmShell::Get()->RemoveLockStateObserver(this); - WmShell::Get()->GetSessionStateDelegate()->RemoveSessionStateObserver(this); + WmShell::Get()->session_controller()->RemoveSessionStateObserver(this); } void ShelfLayoutManager::PrepareForShutdown() { @@ -208,7 +237,7 @@ WmWindow* shelf_window = WmLookup::Get()->GetWindowForWidget(shelf_widget_); if (in_shutdown_ || !wm_shelf_->IsShelfInitialized() || !shelf_window) return; - if (state_.is_screen_locked || state_.is_adding_user_screen) { + if (state_.IsScreenLocked() || state_.IsAddingSecondaryUser()) { SetState(SHELF_VISIBLE); } else if (WmShell::Get()->IsPinned()) { SetState(SHELF_HIDDEN); @@ -296,7 +325,7 @@ void ShelfLayoutManager::SetWindowOverlapsShelf(bool value) { window_overlaps_shelf_ = value; - UpdateShelfBackground(BACKGROUND_CHANGE_ANIMATE); + MaybeUpdateShelfBackground(BACKGROUND_CHANGE_ANIMATE); } void ShelfLayoutManager::AddObserver(ShelfLayoutManagerObserver* observer) { @@ -365,13 +394,6 @@ } } -void ShelfLayoutManager::OnLockStateChanged(bool locked) { - // Force the shelf to layout for alignment (bottom if locked, restore - // the previous alignment otherwise). - state_.is_screen_locked = locked; - UpdateShelfVisibilityAfterLoginUIChange(); -} - void ShelfLayoutManager::OnShelfAutoHideBehaviorChanged(WmWindow* root_window) { UpdateVisibilityState(); } @@ -418,15 +440,20 @@ } ShelfBackgroundType ShelfLayoutManager::GetShelfBackgroundType() const { + if (state_.pre_lock_screen_animation_active) + return SHELF_BACKGROUND_DEFAULT; + + // Handle all non active screen states, including OOBE and pre-login. + if (state_.session_state != session_manager::SessionState::ACTIVE) + return SHELF_BACKGROUND_OVERLAP; + if (state_.visibility_state != SHELF_AUTO_HIDE && state_.window_state == wm::WORKSPACE_WINDOW_STATE_MAXIMIZED) { return SHELF_BACKGROUND_MAXIMIZED; } if (gesture_drag_status_ == GESTURE_DRAG_IN_PROGRESS || - (!state_.is_screen_locked && !state_.is_adding_user_screen && - window_overlaps_shelf_) || - (state_.visibility_state == SHELF_AUTO_HIDE)) { + window_overlaps_shelf_ || state_.visibility_state == SHELF_AUTO_HIDE) { return SHELF_BACKGROUND_OVERLAP; } @@ -456,8 +483,9 @@ state.window_state = controller ? controller->GetWorkspaceWindowState() : wm::WORKSPACE_WINDOW_STATE_DEFAULT; // Preserve the log in screen states. - state.is_adding_user_screen = state_.is_adding_user_screen; - state.is_screen_locked = state_.is_screen_locked; + state.session_state = state_.session_state; + state.pre_lock_screen_animation_active = + state_.pre_lock_screen_animation_active; // Force an update because gesture drags affect the shelf bounds and we // should animate back to the normal bounds at the end of a gesture. @@ -501,10 +529,10 @@ if (delay_background_change) { if (update_shelf_observer_) update_shelf_observer_->Detach(); - // UpdateShelfBackground deletes itself when the animation is done. + // |update_shelf_observer_| deletes itself when the animation is done. update_shelf_observer_ = new UpdateShelfObserver(this); } else { - UpdateShelfBackground(change_type); + MaybeUpdateShelfBackground(change_type); } TargetBounds target_bounds; @@ -583,14 +611,14 @@ // For crbug.com/622431, when the shelf alignment is BOTTOM_LOCKED, we // don't set display work area, as it is not real user-set alignment. - if (!state_.is_screen_locked && + if (!state_.IsScreenLocked() && shelf_widget_->GetAlignment() != SHELF_ALIGNMENT_BOTTOM_LOCKED && change_work_area) { gfx::Insets insets; // If user session is blocked (login to new user session or add user to // the existing session - multi-profile) then give 100% of work area only // if keyboard is not shown. - if (!state_.is_adding_user_screen || !keyboard_bounds_.IsEmpty()) + if (!state_.IsAddingSecondaryUser() || !keyboard_bounds_.IsEmpty()) insets = target_bounds.work_area_insets; WmShell::Get()->SetDisplayWorkAreaInsets(shelf_window, insets); } @@ -790,11 +818,16 @@ } } -void ShelfLayoutManager::UpdateShelfBackground( +void ShelfLayoutManager::MaybeUpdateShelfBackground( BackgroundAnimatorChangeType type) { - const ShelfBackgroundType background_type(GetShelfBackgroundType()); + const ShelfBackgroundType new_background_type(GetShelfBackgroundType()); + + if (new_background_type == shelf_background_type_) + return; + + shelf_background_type_ = new_background_type; for (auto& observer : observers_) - observer.OnBackgroundUpdated(background_type, type); + observer.OnBackgroundUpdated(shelf_background_type_, type); } void ShelfLayoutManager::UpdateAutoHideStateNow() { @@ -952,7 +985,7 @@ dock_bounds_ = dock_bounds; OnWindowResized(); UpdateVisibilityState(); - UpdateShelfBackground(BACKGROUND_CHANGE_ANIMATE); + MaybeUpdateShelfBackground(BACKGROUND_CHANGE_ANIMATE); } } @@ -960,21 +993,32 @@ if (event == EVENT_LOCK_ANIMATION_STARTED) { // Enter the screen locked state and update the visibility to avoid an odd // animation when transitioning the orientation from L/R to bottom. - state_.is_screen_locked = true; + state_.pre_lock_screen_animation_active = true; UpdateShelfVisibilityAfterLoginUIChange(); + } else { + state_.pre_lock_screen_animation_active = false; } + MaybeUpdateShelfBackground(BACKGROUND_CHANGE_ANIMATE); } void ShelfLayoutManager::SessionStateChanged( session_manager::SessionState state) { // Check transition changes to/from the add user to session and change the // shelf alignment accordingly - const bool add_user = state == session_manager::SessionState::LOGIN_SECONDARY; - if (add_user != state_.is_adding_user_screen) { - state_.is_adding_user_screen = add_user; + const bool was_adding_user = state_.IsAddingSecondaryUser(); + const bool was_locked = state_.IsScreenLocked(); + state_.session_state = state; + MaybeUpdateShelfBackground(BACKGROUND_CHANGE_ANIMATE); + if (was_adding_user != state_.IsAddingSecondaryUser()) { UpdateShelfVisibilityAfterLoginUIChange(); return; } + + // Force the shelf to layout for alignment (bottom if locked, restore the + // previous alignment otherwise). + if (was_locked != state_.IsScreenLocked()) + UpdateShelfVisibilityAfterLoginUIChange(); + TargetBounds target_bounds; CalculateTargetBounds(state_, &target_bounds); UpdateBoundsAndOpacity(target_bounds, true /* animate */, @@ -1020,7 +1064,7 @@ gesture_drag_auto_hide_state_ = visibility_state() == SHELF_AUTO_HIDE ? auto_hide_state() : SHELF_AUTO_HIDE_SHOWN; - UpdateShelfBackground(BACKGROUND_CHANGE_ANIMATE); + MaybeUpdateShelfBackground(BACKGROUND_CHANGE_ANIMATE); } void ShelfLayoutManager::UpdateGestureDrag(const ui::GestureEvent& gesture) {
diff --git a/ash/common/shelf/shelf_layout_manager.h b/ash/common/shelf/shelf_layout_manager.h index e0eda19..9f2834b3 100644 --- a/ash/common/shelf/shelf_layout_manager.h +++ b/ash/common/shelf/shelf_layout_manager.h
@@ -132,7 +132,6 @@ const gfx::Rect& requested_bounds) override; // Overridden from ShellObserver: - void OnLockStateChanged(bool locked) override; void OnShelfAutoHideBehaviorChanged(WmWindow* root_window) override; void OnPinnedStateChanged(WmWindow* pinned_window) override; @@ -178,7 +177,7 @@ // Is the shelf's alignment horizontal? bool IsHorizontalAlignment() const; - // Returns how the shelf background is painted. + // Returns how the shelf background should be painted. ShelfBackgroundType GetShelfBackgroundType() const; // Set the height of the ChromeVox panel, which takes away space from the @@ -204,31 +203,25 @@ }; struct State { - State() - : visibility_state(SHELF_VISIBLE), - auto_hide_state(SHELF_AUTO_HIDE_HIDDEN), - window_state(wm::WORKSPACE_WINDOW_STATE_DEFAULT), - is_screen_locked(false), - is_adding_user_screen(false) {} + State(); + + // Returns true when a secondary user is being added to an existing session. + bool IsAddingSecondaryUser() const; + + bool IsScreenLocked() const; // Returns true if the two states are considered equal. As // |auto_hide_state| only matters if |visibility_state| is // |SHELF_AUTO_HIDE|, Equals() ignores the |auto_hide_state| as // appropriate. - bool Equals(const State& other) const { - return other.visibility_state == visibility_state && - (visibility_state != SHELF_AUTO_HIDE || - other.auto_hide_state == auto_hide_state) && - other.window_state == window_state && - other.is_screen_locked == is_screen_locked && - other.is_adding_user_screen == is_adding_user_screen; - } + bool Equals(const State& other) const; ShelfVisibilityState visibility_state; ShelfAutoHideState auto_hide_state; wm::WorkspaceWindowState window_state; - bool is_screen_locked; - bool is_adding_user_screen; + // True when the system is in the cancelable, pre-lock screen animation. + bool pre_lock_screen_animation_active; + session_manager::SessionState session_state; }; // Sets the visibility of the shelf to |state|. @@ -253,8 +246,8 @@ // used by |CalculateTargetBounds()|. void UpdateTargetBoundsForGesture(TargetBounds* target_bounds) const; - // Updates the background of the shelf. - void UpdateShelfBackground(BackgroundAnimatorChangeType type); + // Updates the background of the shelf if it has changed. + void MaybeUpdateShelfBackground(BackgroundAnimatorChangeType change_type); // Updates the auto hide state immediately. void UpdateAutoHideStateNow(); @@ -365,6 +358,10 @@ // The show hide animation duration override or 0 for default. int duration_override_in_ms_; + // The current shelf background. Should not be assigned to directly, use + // MaybeUpdateShelfBackground() instead. + ShelfBackgroundType shelf_background_type_; + DISALLOW_COPY_AND_ASSIGN(ShelfLayoutManager); };
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc index d3424f0..9cafd20 100644 --- a/ash/shelf/shelf_layout_manager_unittest.cc +++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -8,7 +8,7 @@ #include "ash/common/accelerators/accelerator_table.h" #include "ash/common/focus_cycler.h" #include "ash/common/material_design/material_design_controller.h" -#include "ash/common/session/session_state_delegate.h" +#include "ash/common/session/session_controller.h" #include "ash/common/shelf/shelf_constants.h" #include "ash/common/shelf/shelf_layout_manager_observer.h" #include "ash/common/shelf/shelf_view.h" @@ -26,6 +26,7 @@ #include "ash/test/ash_test_base.h" #include "ash/test/test_app_list_view_presenter_impl.h" #include "ash/test/test_system_tray_item.h" +#include "ash/wm/lock_state_controller.h" #include "ash/wm/window_state_aura.h" #include "ash/wm/window_util.h" #include "base/command_line.h" @@ -302,16 +303,16 @@ // Turn on the lock screen. void LockScreen() { - WmShell::Get()->GetSessionStateDelegate()->LockScreen(); - // The test session state delegate does not fire the lock state change. - Shell::GetInstance()->OnLockStateChanged(true); + mojom::SessionInfoPtr info = mojom::SessionInfo::New(); + info->state = session_manager::SessionState::LOCKED; + ash::WmShell::Get()->session_controller()->SetSessionInfo(std::move(info)); } // Turn off the lock screen. void UnlockScreen() { - WmShell::Get()->GetSessionStateDelegate()->UnlockScreen(); - // The test session state delegate does not fire the lock state change. - Shell::GetInstance()->OnLockStateChanged(false); + mojom::SessionInfoPtr info = mojom::SessionInfo::New(); + info->state = session_manager::SessionState::ACTIVE; + ash::WmShell::Get()->session_controller()->SetSessionInfo(std::move(info)); } private: @@ -841,6 +842,18 @@ EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState()); } +// Assertions around the login screen. +TEST_F(ShelfLayoutManagerTest, VisibleWhenLoginScreenShowing) { + WmShelf* shelf = GetPrimaryShelf(); + + mojom::SessionInfoPtr info = mojom::SessionInfo::New(); + info->state = session_manager::SessionState::LOGIN_PRIMARY; + ash::WmShell::Get()->session_controller()->SetSessionInfo(std::move(info)); + + EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState()); + EXPECT_EQ(SHELF_BACKGROUND_OVERLAP, GetShelfWidget()->GetBackgroundType()); +} + // Assertions around the lock screen showing. TEST_F(ShelfLayoutManagerTest, VisibleWhenLockScreenShowing) { WmShelf* shelf = GetPrimaryShelf(); @@ -866,9 +879,11 @@ LockScreen(); // Showing a widget in the lock screen should force the shelf to be visibile. EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState()); + EXPECT_EQ(SHELF_BACKGROUND_OVERLAP, GetShelfWidget()->GetBackgroundType()); UnlockScreen(); EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState()); + EXPECT_EQ(SHELF_BACKGROUND_OVERLAP, GetShelfWidget()->GetBackgroundType()); } // Assertions around SetAutoHideBehavior. @@ -1562,7 +1577,22 @@ } } +TEST_F(ShelfLayoutManagerTest, BackgroundTypeWhenLockingScreen) { + EXPECT_NE(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType()); + + Shell::GetInstance() + ->lock_state_controller() + ->StartLockAnimationAndLockImmediately(false); + EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType()); +} + TEST_F(ShelfLayoutManagerTest, ShelfBackgroundColor) { + // TODO(bruthig|xiyuan): Move SessionState setup into AshTestBase or + // AshTestHelper. + mojom::SessionInfoPtr info = mojom::SessionInfo::New(); + info->state = session_manager::SessionState::ACTIVE; + ash::WmShell::Get()->session_controller()->SetSessionInfo(std::move(info)); + EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType()); std::unique_ptr<aura::Window> w1(CreateTestWindow()); @@ -1595,6 +1625,12 @@ // Verify that the shelf doesn't have the opaque background if it's auto-hide // status. TEST_F(ShelfLayoutManagerTest, ShelfBackgroundColorAutoHide) { + // TODO(bruthig|xiyuan): Move SessionState setup into AshTestBase or + // AshTestHelper. + mojom::SessionInfoPtr info = mojom::SessionInfo::New(); + info->state = session_manager::SessionState::ACTIVE; + ash::WmShell::Get()->session_controller()->SetSessionInfo(std::move(info)); + EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType()); GetPrimaryShelf()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
diff --git a/ash/wm/workspace_controller_unittest.cc b/ash/wm/workspace_controller_unittest.cc index c45f8bb2..b5c66ae 100644 --- a/ash/wm/workspace_controller_unittest.cc +++ b/ash/wm/workspace_controller_unittest.cc
@@ -6,6 +6,7 @@ #include <map> +#include "ash/common/session/session_controller.h" #include "ash/common/shelf/shelf_layout_manager.h" #include "ash/common/shelf/shelf_widget.h" #include "ash/common/shelf/wm_shelf.h" @@ -14,6 +15,7 @@ #include "ash/common/wm/panels/panel_layout_manager.h" #include "ash/common/wm/window_state.h" #include "ash/common/wm/workspace/workspace_window_resizer.h" +#include "ash/common/wm_shell.h" #include "ash/common/wm_window.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/screen_util.h" @@ -506,6 +508,12 @@ // Verifies going from maximized to minimized sets the right state for painting // the background of the launcher. TEST_P(WorkspaceControllerTest, MinimizeResetsVisibility) { + // TODO(bruthig|xiyuan): Move SessionState setup into AshTestBase or + // AshTestHelper. + mojom::SessionInfoPtr info = mojom::SessionInfo::New(); + info->state = session_manager::SessionState::ACTIVE; + ash::WmShell::Get()->session_controller()->SetSessionInfo(std::move(info)); + std::unique_ptr<Window> w1(CreateTestWindow()); w1->Show(); wm::ActivateWindow(w1.get());
diff --git a/base/android/java/src/org/chromium/base/library_loader/ModernLinker.java b/base/android/java/src/org/chromium/base/library_loader/ModernLinker.java index 7669e0ee..db03e03 100644 --- a/base/android/java/src/org/chromium/base/library_loader/ModernLinker.java +++ b/base/android/java/src/org/chromium/base/library_loader/ModernLinker.java
@@ -251,8 +251,6 @@ Log.i(TAG, "disableSharedRelros() called"); } synchronized (mLock) { - assert !mPrepareLibraryLoadCalled; - // Mark this as a service process, and disable wait for shared RELRO. mInBrowserProcess = false; mWaitForSharedRelros = false;
diff --git a/base/cpu.cc b/base/cpu.cc index 2532816..848208f7 100644 --- a/base/cpu.cc +++ b/base/cpu.cc
@@ -16,7 +16,6 @@ #if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX)) #include "base/files/file_util.h" -#include "base/lazy_instance.h" #endif #if defined(ARCH_CPU_X86_FAMILY) @@ -94,9 +93,8 @@ #endif // ARCH_CPU_X86_FAMILY #if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX)) -class LazyCpuInfoValue { - public: - LazyCpuInfoValue() { +std::string* CpuInfoBrand() { + static std::string* brand = []() { // This function finds the value from /proc/cpuinfo under the key "model // name" or "Processor". "model name" is used in Linux 3.8 and later (3.7 // and later for arm64) and is shown once per CPU. "Processor" is used in @@ -109,30 +107,23 @@ ReadFileToString(FilePath("/proc/cpuinfo"), &contents); DCHECK(!contents.empty()); if (contents.empty()) { - return; + return new std::string(); } std::istringstream iss(contents); std::string line; while (std::getline(iss, line)) { - if (brand_.empty() && - (line.compare(0, strlen(kModelNamePrefix), kModelNamePrefix) == 0 || + if ((line.compare(0, strlen(kModelNamePrefix), kModelNamePrefix) == 0 || line.compare(0, strlen(kProcessorPrefix), kProcessorPrefix) == 0)) { - brand_.assign(line.substr(strlen(kModelNamePrefix))); + return new std::string(line.substr(strlen(kModelNamePrefix))); } } - } - const std::string& brand() const { return brand_; } + return new std::string(); + }(); - private: - std::string brand_; - DISALLOW_COPY_AND_ASSIGN(LazyCpuInfoValue); -}; - -base::LazyInstance<LazyCpuInfoValue>::Leaky g_lazy_cpuinfo = - LAZY_INSTANCE_INITIALIZER; - + return brand; +} #endif // defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || // defined(OS_LINUX)) @@ -221,7 +212,7 @@ has_non_stop_time_stamp_counter_ = (cpu_info[3] & (1 << 8)) != 0; } #elif defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX)) - cpu_brand_.assign(g_lazy_cpuinfo.Get().brand()); + cpu_brand_.assign(*CpuInfoBrand()); #endif }
diff --git a/base/debug/close_handle_hook_win.cc b/base/debug/close_handle_hook_win.cc index 168de67..1f2aeab 100644 --- a/base/debug/close_handle_hook_win.cc +++ b/base/debug/close_handle_hook_win.cc
@@ -12,7 +12,6 @@ #include <memory> #include <vector> -#include "base/lazy_instance.h" #include "base/macros.h" #include "base/win/iat_patch_function.h" #include "base/win/pe_image.h" @@ -197,13 +196,11 @@ void AddIATPatch(HMODULE module); void AddEATPatch(); - void Unpatch(); private: std::vector<base::win::IATPatchFunction*> hooks_; DISALLOW_COPY_AND_ASSIGN(HandleHooks); }; -base::LazyInstance<HandleHooks> g_hooks = LAZY_INSTANCE_INITIALIZER; void HandleHooks::AddIATPatch(HMODULE module) { if (!module) @@ -232,14 +229,6 @@ reinterpret_cast<void**>(&g_duplicate_function)); } -void HandleHooks::Unpatch() { - for (std::vector<base::win::IATPatchFunction*>::iterator it = hooks_.begin(); - it != hooks_.end(); ++it) { - (*it)->Unpatch(); - delete *it; - } -} - void PatchLoadedModules(HandleHooks* hooks) { const DWORD kSize = 256; DWORD returned; @@ -259,7 +248,7 @@ } // namespace void InstallHandleHooks() { - HandleHooks* hooks = g_hooks.Pointer(); + static HandleHooks* hooks = new HandleHooks(); // Performing EAT interception first is safer in the presence of other // threads attempting to call CloseHandle. @@ -267,10 +256,5 @@ PatchLoadedModules(hooks); } -void RemoveHandleHooks() { - // We are partching all loaded modules without forcing them to stay in memory, - // removing patches is not safe. -} - } // namespace debug } // namespace base
diff --git a/base/debug/close_handle_hook_win.h b/base/debug/close_handle_hook_win.h index a042467..c775d75 100644 --- a/base/debug/close_handle_hook_win.h +++ b/base/debug/close_handle_hook_win.h
@@ -13,9 +13,6 @@ // Installs the hooks required to debug use of improper handles. BASE_EXPORT void InstallHandleHooks(); -// Removes the hooks installed by InstallHandleHooks(). -BASE_EXPORT void RemoveHandleHooks(); - } // namespace debug } // namespace base
diff --git a/base/memory/memory_pressure_listener.cc b/base/memory/memory_pressure_listener.cc index 27e70018..a421c18b 100644 --- a/base/memory/memory_pressure_listener.cc +++ b/base/memory/memory_pressure_listener.cc
@@ -4,7 +4,6 @@ #include "base/memory/memory_pressure_listener.h" -#include "base/lazy_instance.h" #include "base/observer_list_threadsafe.h" #include "base/trace_event/trace_event.h" @@ -51,8 +50,10 @@ DISALLOW_COPY_AND_ASSIGN(MemoryPressureObserver); }; -LazyInstance<MemoryPressureObserver>::Leaky g_observer = - LAZY_INSTANCE_INITIALIZER; +MemoryPressureObserver* GetMemoryPressureObserver() { + static auto observer = new MemoryPressureObserver(); + return observer; +} subtle::Atomic32 g_notifications_suppressed = 0; @@ -61,7 +62,7 @@ MemoryPressureListener::MemoryPressureListener( const MemoryPressureListener::MemoryPressureCallback& callback) : callback_(callback) { - g_observer.Get().AddObserver(this, false); + GetMemoryPressureObserver()->AddObserver(this, false); } MemoryPressureListener::MemoryPressureListener( @@ -70,11 +71,11 @@ sync_memory_pressure_callback) : callback_(callback), sync_memory_pressure_callback_(sync_memory_pressure_callback) { - g_observer.Get().AddObserver(this, true); + GetMemoryPressureObserver()->AddObserver(this, true); } MemoryPressureListener::~MemoryPressureListener() { - g_observer.Get().RemoveObserver(this); + GetMemoryPressureObserver()->RemoveObserver(this); } void MemoryPressureListener::Notify(MemoryPressureLevel memory_pressure_level) { @@ -123,7 +124,7 @@ MemoryPressureLevel memory_pressure_level) { DCHECK_NE(memory_pressure_level, MEMORY_PRESSURE_LEVEL_NONE); - g_observer.Get().Notify(memory_pressure_level); + GetMemoryPressureObserver()->Notify(memory_pressure_level); } } // namespace base
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc index 2212941d..72185a8 100644 --- a/base/message_loop/message_loop.cc +++ b/base/message_loop/message_loop.cc
@@ -9,7 +9,6 @@ #include "base/bind.h" #include "base/compiler_specific.h" -#include "base/lazy_instance.h" #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/message_loop/message_pump_default.h" @@ -38,10 +37,11 @@ namespace { // A lazily created thread local storage for quick access to a thread's message -// loop, if one exists. This should be safe and free of static constructors. -LazyInstance<base::ThreadLocalPointer<MessageLoop> >::Leaky lazy_tls_ptr = - LAZY_INSTANCE_INITIALIZER; - +// loop, if one exists. +base::ThreadLocalPointer<MessageLoop>* GetTLSMessageLoop() { + static auto lazy_tls_ptr = new base::ThreadLocalPointer<MessageLoop>(); + return lazy_tls_ptr; +} MessageLoop::MessagePumpFactory* message_pump_for_ui_factory_ = NULL; #if defined(OS_IOS) @@ -137,7 +137,7 @@ // OK, now make it so that no one can find us. if (current() == this) - lazy_tls_ptr.Pointer()->Set(nullptr); + GetTLSMessageLoop()->Set(nullptr); } // static @@ -145,7 +145,7 @@ // TODO(darin): sadly, we cannot enable this yet since people call us even // when they have no intention of using us. // DCHECK(loop) << "Ouch, did you forget to initialize me?"; - return lazy_tls_ptr.Pointer()->Get(); + return GetTLSMessageLoop()->Get(); } // static @@ -338,7 +338,7 @@ pump_ = CreateMessagePumpForType(type_); DCHECK(!current()) << "should only have one message loop per thread"; - lazy_tls_ptr.Pointer()->Set(this); + GetTLSMessageLoop()->Set(this); incoming_task_queue_->StartScheduling(); unbound_task_runner_->BindToCurrentThread();
diff --git a/base/path_service.cc b/base/path_service.cc index 3f954d79..17ba0d7 100644 --- a/base/path_service.cc +++ b/base/path_service.cc
@@ -13,7 +13,6 @@ #include "base/containers/hash_tables.h" #include "base/files/file_path.h" #include "base/files/file_util.h" -#include "base/lazy_instance.h" #include "base/logging.h" #include "base/synchronization/lock.h" #include "build/build_config.h" @@ -129,10 +128,9 @@ } }; -static LazyInstance<PathData>::Leaky g_path_data = LAZY_INSTANCE_INITIALIZER; - static PathData* GetPathData() { - return g_path_data.Pointer(); + static auto path_data = new PathData(); + return path_data; } // Tries to find |key| in the cache. |path_data| should be locked by the caller!
diff --git a/base/threading/thread_local_storage.cc b/base/threading/thread_local_storage.cc index 15a1d5e..198a308 100644 --- a/base/threading/thread_local_storage.cc +++ b/base/threading/thread_local_storage.cc
@@ -5,7 +5,6 @@ #include "base/threading/thread_local_storage.h" #include "base/atomicops.h" -#include "base/lazy_instance.h" #include "base/logging.h" #include "base/synchronization/lock.h" #include "build/build_config.h" @@ -90,9 +89,12 @@ uint32_t version; }; -// This LazyInstance isn't needed until after we've constructed the per-thread -// TLS vector, so it's safe to use. -base::LazyInstance<base::Lock>::Leaky g_tls_metadata_lock; +// This lock isn't needed until after we've constructed the per-thread TLS +// vector, so it's safe to use. +base::Lock* GetTLSMetadataLock() { + static auto lock = new base::Lock(); + return lock; +} TlsMetadata g_tls_metadata[kThreadLocalStorageSize]; size_t g_last_assigned_slot = 0; @@ -182,7 +184,7 @@ // Snapshot the TLS Metadata so we don't have to lock on every access. TlsMetadata tls_metadata[kThreadLocalStorageSize]; { - base::AutoLock auto_lock(g_tls_metadata_lock.Get()); + base::AutoLock auto_lock(*GetTLSMetadataLock()); memcpy(tls_metadata, g_tls_metadata, sizeof(g_tls_metadata)); } @@ -261,7 +263,7 @@ slot_ = kInvalidSlotValue; version_ = 0; { - base::AutoLock auto_lock(g_tls_metadata_lock.Get()); + base::AutoLock auto_lock(*GetTLSMetadataLock()); for (int i = 0; i < kThreadLocalStorageSize; ++i) { // Tracking the last assigned slot is an attempt to find the next // available slot within one iteration. Under normal usage, slots remain @@ -291,7 +293,7 @@ DCHECK_NE(slot_, kInvalidSlotValue); DCHECK_LT(slot_, kThreadLocalStorageSize); { - base::AutoLock auto_lock(g_tls_metadata_lock.Get()); + base::AutoLock auto_lock(*GetTLSMetadataLock()); g_tls_metadata[slot_].status = TlsStatus::FREE; g_tls_metadata[slot_].destructor = nullptr; ++(g_tls_metadata[slot_].version);
diff --git a/base/threading/watchdog.cc b/base/threading/watchdog.cc index c0637998..a34c132 100644 --- a/base/threading/watchdog.cc +++ b/base/threading/watchdog.cc
@@ -5,7 +5,6 @@ #include "base/threading/watchdog.h" #include "base/compiler_specific.h" -#include "base/lazy_instance.h" #include "base/logging.h" #include "base/threading/platform_thread.h" @@ -31,7 +30,10 @@ TimeDelta last_debugged_alarm_delay; }; -LazyInstance<StaticData>::Leaky g_static_data = LAZY_INSTANCE_INITIALIZER; +StaticData* GetStaticData() { + static auto static_data = new StaticData(); + return static_data; +} } // namespace @@ -119,7 +121,7 @@ void Watchdog::ThreadDelegate::ThreadMain() { SetThreadName(); TimeDelta remaining_duration; - StaticData* static_data = g_static_data.Pointer(); + StaticData* static_data = GetStaticData(); while (1) { AutoLock lock(watchdog_->lock_); while (DISARMED == watchdog_->state_) @@ -175,7 +177,7 @@ // static void Watchdog::ResetStaticData() { - StaticData* static_data = g_static_data.Pointer(); + StaticData* static_data = GetStaticData(); AutoLock lock(static_data->lock); static_data->last_debugged_alarm_time = TimeTicks(); static_data->last_debugged_alarm_delay = TimeDelta();
diff --git a/base/threading/worker_pool.cc b/base/threading/worker_pool.cc index 6e07b6ef..96a39148 100644 --- a/base/threading/worker_pool.cc +++ b/base/threading/worker_pool.cc
@@ -7,7 +7,6 @@ #include "base/bind.h" #include "base/compiler_specific.h" #include "base/debug/leak_annotations.h" -#include "base/lazy_instance.h" #include "base/macros.h" #include "base/task_runner.h" #include "base/threading/post_task_and_reply_impl.h" @@ -98,9 +97,6 @@ scoped_refptr<TaskRunner> taskrunners_[2]; }; -base::LazyInstance<TaskRunnerHolder>::Leaky - g_taskrunners = LAZY_INSTANCE_INITIALIZER; - } // namespace bool WorkerPool::PostTaskAndReply(const tracked_objects::Location& from_here, @@ -120,7 +116,8 @@ // static const scoped_refptr<TaskRunner>& WorkerPool::GetTaskRunner(bool tasks_are_slow) { - return g_taskrunners.Get().taskrunners_[tasks_are_slow]; + static auto task_runner_holder = new TaskRunnerHolder(); + return task_runner_holder->taskrunners_[tasks_are_slow]; } } // namespace base
diff --git a/base/threading/worker_pool_win.cc b/base/threading/worker_pool_win.cc index d638c0f..1b16bdc 100644 --- a/base/threading/worker_pool_win.cc +++ b/base/threading/worker_pool_win.cc
@@ -16,21 +16,23 @@ namespace { -base::LazyInstance<ThreadLocalBoolean>::Leaky - g_worker_pool_running_on_this_thread = LAZY_INSTANCE_INITIALIZER; +ThreadLocalBoolean* GetWorkerPoolRunningOnThisThread() { + static auto thread_local_boolean = new ThreadLocalBoolean(); + return thread_local_boolean; +} DWORD CALLBACK WorkItemCallback(void* param) { PendingTask* pending_task = static_cast<PendingTask*>(param); TRACE_TASK_EXECUTION("WorkerThread::ThreadMain::Run", *pending_task); - g_worker_pool_running_on_this_thread.Get().Set(true); + GetWorkerPoolRunningOnThisThread()->Set(true); tracked_objects::TaskStopwatch stopwatch; stopwatch.Start(); std::move(pending_task->task).Run(); stopwatch.Stop(); - g_worker_pool_running_on_this_thread.Get().Set(false); + GetWorkerPoolRunningOnThisThread()->Set(false); tracked_objects::ThreadData::TallyRunOnWorkerThreadIfTracking( pending_task->birth_tally, pending_task->time_posted, stopwatch); @@ -65,7 +67,7 @@ // static bool WorkerPool::RunsTasksOnCurrentThread() { - return g_worker_pool_running_on_this_thread.Get().Get(); + return GetWorkerPoolRunningOnThisThread()->Get(); } } // namespace base
diff --git a/base/time/time_posix.cc b/base/time/time_posix.cc index 963c15b..ada2058 100644 --- a/base/time/time_posix.cc +++ b/base/time/time_posix.cc
@@ -26,7 +26,6 @@ #endif #if !defined(OS_MACOSX) -#include "base/lazy_instance.h" #include "base/synchronization/lock.h" #endif @@ -35,8 +34,10 @@ #if !defined(OS_MACOSX) // This prevents a crash on traversing the environment global and looking up // the 'TZ' variable in libc. See: crbug.com/390567. -base::LazyInstance<base::Lock>::Leaky - g_sys_time_to_time_struct_lock = LAZY_INSTANCE_INITIALIZER; +base::Lock* GetSysTimeToTimeStructLock() { + static auto lock = new base::Lock(); + return lock; +} // Define a system-specific SysTime that wraps either to a time_t or // a time64_t depending on the host system, and associated convertion. @@ -45,7 +46,7 @@ typedef time64_t SysTime; SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) { - base::AutoLock locked(g_sys_time_to_time_struct_lock.Get()); + base::AutoLock locked(*GetSysTimeToTimeStructLock()); if (is_local) return mktime64(timestruct); else @@ -53,7 +54,7 @@ } void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) { - base::AutoLock locked(g_sys_time_to_time_struct_lock.Get()); + base::AutoLock locked(*GetSysTimeToTimeStructLock()); if (is_local) localtime64_r(&t, timestruct); else @@ -64,7 +65,7 @@ typedef time_t SysTime; SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) { - base::AutoLock locked(g_sys_time_to_time_struct_lock.Get()); + base::AutoLock locked(*GetSysTimeToTimeStructLock()); if (is_local) return mktime(timestruct); else @@ -72,7 +73,7 @@ } void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) { - base::AutoLock locked(g_sys_time_to_time_struct_lock.Get()); + base::AutoLock locked(*GetSysTimeToTimeStructLock()); if (is_local) localtime_r(&t, timestruct); else
diff --git a/base/time/time_win.cc b/base/time/time_win.cc index 19144cb..75f398d6 100644 --- a/base/time/time_win.cc +++ b/base/time/time_win.cc
@@ -40,7 +40,6 @@ #include "base/atomicops.h" #include "base/bit_cast.h" #include "base/cpu.h" -#include "base/lazy_instance.h" #include "base/logging.h" #include "base/synchronization/lock.h" #include "base/threading/platform_thread.h" @@ -97,8 +96,10 @@ // How many times the high resolution timer has been called. uint32_t g_high_res_timer_count = 0; // The lock to control access to the above two variables. -base::LazyInstance<base::Lock>::Leaky g_high_res_lock = - LAZY_INSTANCE_INITIALIZER; +base::Lock* GetHighResLock() { + static auto lock = new base::Lock(); + return lock; +} // Returns the current value of the performance counter. uint64_t QPCNowRaw() { @@ -191,7 +192,7 @@ // static void Time::EnableHighResolutionTimer(bool enable) { - base::AutoLock lock(g_high_res_lock.Get()); + base::AutoLock lock(*GetHighResLock()); if (g_high_res_timer_enabled == enable) return; g_high_res_timer_enabled = enable; @@ -218,7 +219,7 @@ // called. const uint32_t max = std::numeric_limits<uint32_t>::max(); - base::AutoLock lock(g_high_res_lock.Get()); + base::AutoLock lock(*GetHighResLock()); UINT period = g_high_res_timer_enabled ? kMinTimerIntervalHighResMs : kMinTimerIntervalLowResMs; if (activating) { @@ -237,7 +238,7 @@ // static bool Time::IsHighResolutionTimerInUse() { - base::AutoLock lock(g_high_res_lock.Get()); + base::AutoLock lock(*GetHighResLock()); return g_high_res_timer_enabled && g_high_res_timer_count > 0; }
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc index edfd648..54e4cfee 100644 --- a/base/trace_event/trace_log.cc +++ b/base/trace_event/trace_log.cc
@@ -13,7 +13,6 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/debug/leak_annotations.h" -#include "base/lazy_instance.h" #include "base/location.h" #include "base/macros.h" #include "base/memory/ptr_util.h" @@ -89,14 +88,10 @@ #define MAX_TRACE_EVENT_FILTERS 32 // List of TraceEventFilter objects from the most recent tracing session. -base::LazyInstance<std::vector<std::unique_ptr<TraceEventFilter>>>::Leaky - g_category_group_filters = LAZY_INSTANCE_INITIALIZER; - -// The name of the current thread. This is used to decide if the current -// thread name has changed. We combine all the seen thread names into the -// output name for the thread. -LazyInstance<ThreadLocalPointer<const char>>::Leaky g_current_thread_name = - LAZY_INSTANCE_INITIALIZER; +std::vector<std::unique_ptr<TraceEventFilter>>& GetCategoryGroupFilters() { + static auto filters = new std::vector<std::unique_ptr<TraceEventFilter>>(); + return *filters; +} ThreadTicks ThreadNow() { return ThreadTicks::IsSupported() ? ThreadTicks::Now() : ThreadTicks(); @@ -169,8 +164,8 @@ CategoryRegistry::GetCategoryByStatePtr(category_group_enabled); uint32_t filter_bitmap = category->enabled_filters(); for (int index = 0; filter_bitmap != 0; filter_bitmap >>= 1, index++) { - if (filter_bitmap & 1 && g_category_group_filters.Get()[index]) - filter_fn(g_category_group_filters.Get()[index].get()); + if (filter_bitmap & 1 && GetCategoryGroupFilters()[index]) + filter_fn(GetCategoryGroupFilters()[index].get()); } } @@ -473,7 +468,7 @@ for (const auto& event_filter : enabled_event_filters_) { if (event_filter.IsCategoryGroupEnabled(category->name())) { state_flags |= TraceCategory::ENABLED_FOR_FILTERING; - DCHECK(g_category_group_filters.Get()[index]); + DCHECK(GetCategoryGroupFilters()[index]); enabled_filters_bitmap |= 1 << index; } if (index++ >= MAX_TRACE_EVENT_FILTERS) { @@ -499,11 +494,11 @@ // 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()) + if (GetCategoryGroupFilters().size()) return; for (auto& filter_config : enabled_event_filters_) { - if (g_category_group_filters.Get().size() >= MAX_TRACE_EVENT_FILTERS) { + if (GetCategoryGroupFilters().size() >= MAX_TRACE_EVENT_FILTERS) { NOTREACHED() << "Too many trace event filters installed in the current session"; break; @@ -522,7 +517,7 @@ new_filter = filter_factory_for_testing_(predicate_name); CHECK(new_filter) << "Unknown trace filter " << predicate_name; } - g_category_group_filters.Get().push_back(std::move(new_filter)); + GetCategoryGroupFilters().push_back(std::move(new_filter)); } } @@ -589,7 +584,7 @@ // 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(); + GetCategoryGroupFilters().clear(); // Update trace config for recording. const bool already_recording = enabled_modes_ & RECORDING_MODE; @@ -1220,9 +1215,9 @@ // call (if any), but don't bother if the new name is empty. Note this will // not detect a thread name change within the same char* buffer address: we // favor common case performance over corner case correctness. - if (new_name != g_current_thread_name.Get().Get() && new_name && - *new_name) { - g_current_thread_name.Get().Set(new_name); + static auto current_thread_name = new ThreadLocalPointer<const char>(); + if (new_name != current_thread_name->Get() && new_name && *new_name) { + current_thread_name->Set(new_name); AutoLock thread_info_lock(thread_info_lock_);
diff --git a/base/win/scoped_handle.cc b/base/win/scoped_handle.cc index 6d152aec..47ab854 100644 --- a/base/win/scoped_handle.cc +++ b/base/win/scoped_handle.cc
@@ -11,7 +11,6 @@ #include "base/debug/alias.h" #include "base/debug/stack_trace.h" #include "base/hash.h" -#include "base/lazy_instance.h" #include "base/logging.h" #include "base/macros.h" #include "base/synchronization/lock_impl.h" @@ -43,10 +42,13 @@ }; typedef std::unordered_map<HANDLE, Info, HandleHash> HandleMap; -// g_lock protects the handle map and setting g_active_verifier within this +// GetLock() protects the handle map and setting g_active_verifier within this // module. typedef base::internal::LockImpl NativeLock; -base::LazyInstance<NativeLock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER; +NativeLock* GetLock() { + static auto native_lock = new NativeLock(); + return native_lock; +} // Simple automatic locking using a native critical section so it supports // recursive locking. @@ -70,9 +72,7 @@ // way to delete this object from the wrong side of it (or any side, actually). class ActiveVerifier { public: - explicit ActiveVerifier(bool enabled) - : enabled_(enabled), lock_(g_lock.Pointer()) { - } + explicit ActiveVerifier(bool enabled) : enabled_(enabled), lock_(GetLock()) {} // Retrieves the current verifier. static ActiveVerifier* Get(); @@ -117,11 +117,11 @@ return true; } -// Assigns the g_active_verifier global within the g_lock lock. +// Assigns the g_active_verifier global within the GetLock() lock. // If |existing_verifier| is non-null then |enabled| is ignored. void ThreadSafeAssignOrCreateActiveVerifier(ActiveVerifier* existing_verifier, bool enabled) { - AutoNativeLock lock(g_lock.Get()); + AutoNativeLock lock(*GetLock()); // Another thread in this module might be trying to assign the global // verifier, so check that within the lock here. if (g_active_verifier)
diff --git a/base/win/win_util.cc b/base/win/win_util.cc index 3b7d319..a1b7f89 100644 --- a/base/win/win_util.cc +++ b/base/win/win_util.cc
@@ -32,7 +32,6 @@ #include "base/base_switches.h" #include "base/command_line.h" -#include "base/lazy_instance.h" #include "base/logging.h" #include "base/macros.h" #include "base/strings/string_util.h" @@ -67,44 +66,6 @@ *((volatile int*)0) = 0x1337; } -typedef decltype(GetProcessMitigationPolicy)* GetProcessMitigationPolicyType; - -class LazyIsUser32AndGdi32Available { - public: - LazyIsUser32AndGdi32Available() : value_(!IsWin32kSyscallsDisabled()) {} - - ~LazyIsUser32AndGdi32Available() {} - - bool value() { return value_; } - - private: - static bool IsWin32kSyscallsDisabled() { - // Can't disable win32k prior to windows 8. - if (base::win::GetVersion() < base::win::VERSION_WIN8) - return false; - - GetProcessMitigationPolicyType get_process_mitigation_policy_func = - reinterpret_cast<GetProcessMitigationPolicyType>(GetProcAddress( - GetModuleHandle(L"kernel32.dll"), "GetProcessMitigationPolicy")); - - if (!get_process_mitigation_policy_func) - return false; - - PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY policy = {}; - if (get_process_mitigation_policy_func(GetCurrentProcess(), - ProcessSystemCallDisablePolicy, - &policy, sizeof(policy))) { - return policy.DisallowWin32kSystemCalls != 0; - } - - return false; - } - - const bool value_; - - DISALLOW_COPY_AND_ASSIGN(LazyIsUser32AndGdi32Available); -}; - // Returns the current platform role. We use the PowerDeterminePlatformRoleEx // API for that. POWER_PLATFORM_ROLE GetPlatformRole() { @@ -540,9 +501,32 @@ } bool IsUser32AndGdi32Available() { - static base::LazyInstance<LazyIsUser32AndGdi32Available>::Leaky available = - LAZY_INSTANCE_INITIALIZER; - return available.Get().value(); + static auto is_user32_and_gdi32_available = []() { + // If win32k syscalls aren't disabled, then user32 and gdi32 are available. + + // Can't disable win32k prior to windows 8. + if (base::win::GetVersion() < base::win::VERSION_WIN8) + return true; + + typedef decltype( + GetProcessMitigationPolicy)* GetProcessMitigationPolicyType; + GetProcessMitigationPolicyType get_process_mitigation_policy_func = + reinterpret_cast<GetProcessMitigationPolicyType>(GetProcAddress( + GetModuleHandle(L"kernel32.dll"), "GetProcessMitigationPolicy")); + + if (!get_process_mitigation_policy_func) + return true; + + PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY policy = {}; + if (get_process_mitigation_policy_func(GetCurrentProcess(), + ProcessSystemCallDisablePolicy, + &policy, sizeof(policy))) { + return policy.DisallowWin32kSystemCalls == 0; + } + + return true; + }(); + return is_user32_and_gdi32_available; } bool GetLoadedModulesSnapshot(HANDLE process, std::vector<HMODULE>* snapshot) {
diff --git a/build/config/sanitizers/sanitizers.gni b/build/config/sanitizers/sanitizers.gni index 512b44b..a0e9940 100644 --- a/build/config/sanitizers/sanitizers.gni +++ b/build/config/sanitizers/sanitizers.gni
@@ -139,7 +139,7 @@ asan_globals = !is_mac } -if ((use_afl || use_libfuzzer) && sanitizer_coverage_flags == "") { +if (use_afl && sanitizer_coverage_flags == "") { sanitizer_coverage_flags = "trace-pc-guard" } else if (use_sanitizer_coverage && sanitizer_coverage_flags == "") { sanitizer_coverage_flags = "edge,indirect-calls,8bit-counters"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/compositor/OWNERS index c853dcd..c0500c0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/OWNERS +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/OWNERS
@@ -1,4 +1,3 @@ changwan@chromium.org dtrainor@chromium.org - -per-file Compositor*=mdjones@chromium.org +mdjones@chromium.org
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/ActionItem.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/ActionItem.java index 3e69224..ddcb2e39 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/ActionItem.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/ActionItem.java
@@ -20,24 +20,22 @@ /** * Item that allows the user to perform an action on the NTP. - * Note: Use {@link #refreshVisibility()} to update the visibility of the button instead of calling - * {@link #setVisible(boolean)} directly. */ public class ActionItem extends OptionalLeaf { - @IntDef({ACTION_NONE, ACTION_VIEW_ALL, ACTION_FETCH_MORE, ACTION_RELOAD}) + @IntDef({ACTION_NONE, ACTION_VIEW_ALL, ACTION_FETCH}) @Retention(RetentionPolicy.SOURCE) public @interface Action {} public static final int ACTION_NONE = 0; public static final int ACTION_VIEW_ALL = 1; - public static final int ACTION_FETCH_MORE = 2; - public static final int ACTION_RELOAD = 3; + public static final int ACTION_FETCH = 2; private final SuggestionsCategoryInfo mCategoryInfo; private final SuggestionsSection mParentSection; private final SuggestionsRanker mSuggestionsRanker; @Action - private int mCurrentAction = ACTION_NONE; + private final int mCurrentAction; + private boolean mImpressionTracked; private int mPerSectionRank = -1; @@ -45,10 +43,6 @@ mCategoryInfo = section.getCategoryInfo(); mParentSection = section; mSuggestionsRanker = ranker; - } - - /** Call this instead of {@link #setVisible(boolean)} to update the visibility. */ - public void refreshVisibility() { mCurrentAction = findAppropriateAction(); setVisible(mCurrentAction != ACTION_NONE); } @@ -86,8 +80,7 @@ case ACTION_VIEW_ALL: mCategoryInfo.performViewAllAction(uiDelegate.getNavigationDelegate()); return; - case ACTION_FETCH_MORE: - case ACTION_RELOAD: + case ACTION_FETCH: uiDelegate.getSuggestionsSource().fetchSuggestions( mCategoryInfo.getCategory(), mParentSection.getDisplayedSuggestionIds()); mParentSection.onFetchStarted(); @@ -101,10 +94,8 @@ @Action private int findAppropriateAction() { - boolean hasSuggestions = mParentSection.hasSuggestions(); if (mCategoryInfo.hasViewAllAction()) return ACTION_VIEW_ALL; - if (hasSuggestions && mCategoryInfo.hasFetchMoreAction()) return ACTION_FETCH_MORE; - if (!hasSuggestions && mCategoryInfo.hasReloadAction()) return ACTION_RELOAD; + if (mCategoryInfo.hasFetchAction()) return ACTION_FETCH; return ACTION_NONE; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfo.java index 7f333ef2..8145913f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfo.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsCategoryInfo.java
@@ -39,18 +39,11 @@ private final int mCardLayout; /** - * Whether the category supports a "More" action, that triggers fetching more suggestions for - * the category, while keeping the current ones. + * Whether the category supports a "Fetch" action, that triggers fetching more suggestions for + * the category. * @see ActionItem */ - private final boolean mHasFetchMoreAction; - - /** - * Whether the category supports a "Reload" action, that triggers fetching new suggestions to - * replace the current ones. - * @see ActionItem - */ - private final boolean mHasReloadAction; + private final boolean mHasFetchAction; /** * Whether the category supports a "ViewAll" action, that triggers displaying all the content @@ -69,14 +62,12 @@ private final String mNoSuggestionsMessage; public SuggestionsCategoryInfo(@CategoryInt int category, String title, - @ContentSuggestionsCardLayoutEnum int cardLayout, boolean hasMoreAction, - boolean hasReloadAction, boolean hasViewAllAction, boolean showIfEmpty, - String noSuggestionsMessage) { + @ContentSuggestionsCardLayoutEnum int cardLayout, boolean hasFetchAction, + boolean hasViewAllAction, boolean showIfEmpty, String noSuggestionsMessage) { mCategory = category; mTitle = title; mCardLayout = cardLayout; - mHasFetchMoreAction = hasMoreAction; - mHasReloadAction = hasReloadAction; + mHasFetchAction = hasFetchAction; mHasViewAllAction = hasViewAllAction; mShowIfEmpty = showIfEmpty; mNoSuggestionsMessage = noSuggestionsMessage; @@ -96,12 +87,8 @@ return mCardLayout; } - public boolean hasFetchMoreAction() { - return mHasFetchMoreAction; - } - - public boolean hasReloadAction() { - return mHasReloadAction; + public boolean hasFetchAction() { + return mHasFetchAction; } public boolean hasViewAllAction() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java index b3eca40..e5bebb4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
@@ -242,7 +242,6 @@ private void refreshChildrenVisibility() { mStatus.setVisible(!hasSuggestions()); - mMoreButton.refreshVisibility(); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java index 8f99716..716439a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsBridge.java
@@ -286,10 +286,10 @@ @CalledByNative private static SuggestionsCategoryInfo createSuggestionsCategoryInfo(int category, String title, - int cardLayout, boolean hasMoreAction, boolean hasReloadAction, - boolean hasViewAllAction, boolean showIfEmpty, String noSuggestionsMessage) { - return new SuggestionsCategoryInfo(category, title, cardLayout, hasMoreAction, - hasReloadAction, hasViewAllAction, showIfEmpty, noSuggestionsMessage); + int cardLayout, boolean hasFetchAction, boolean hasViewAllAction, boolean showIfEmpty, + String noSuggestionsMessage) { + return new SuggestionsCategoryInfo(category, title, cardLayout, hasFetchAction, + hasViewAllAction, showIfEmpty, noSuggestionsMessage); } @CalledByNative
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerViewTest.java index 0c3c0d0..c66f2ed01 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerViewTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerViewTest.java
@@ -65,9 +65,8 @@ mSource = new FakeSuggestionsSource(); mSource.setInfoForCategory(KnownCategories.ARTICLES, new SuggestionsCategoryInfo(KnownCategories.ARTICLES, "Articles test title", - ContentSuggestionsCardLayout.FULL_CARD, /*hasMoreAction=*/true, - /*hasReloadAction=*/true, /*hasViewAllAction=*/false, /*showIfEmpty=*/true, - "noSuggestionsMessage")); + ContentSuggestionsCardLayout.FULL_CARD, /*hasFetchAction=*/true, + /*hasViewAllAction=*/false, /*showIfEmpty=*/true, "noSuggestionsMessage")); mSource.setStatusForCategory(KnownCategories.ARTICLES, CategoryStatus.INITIALIZING); NewTabPage.setSuggestionsSourceForTests(mSource);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java index 035184630c..b0bb71a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/snippets/ArticleSnippetsTest.java
@@ -156,16 +156,20 @@ mSnippetsSource.setInfoForCategory( fullCategory, new SuggestionsCategoryInfo(fullCategory, "Section Title", - ContentSuggestionsCardLayout.FULL_CARD, false, false, false, - true, "No suggestions")); + ContentSuggestionsCardLayout.FULL_CARD, + /*has_fetch_action=*/false, + /*has_view_all_action=*/false, + /*show_if_empty=*/true, "No suggestions")); mSnippetsSource.setStatusForCategory(fullCategory, CategoryStatus.AVAILABLE); mSnippetsSource.setSuggestionsForCategory( fullCategory, Arrays.asList(shortSnippet, longSnippet)); mSnippetsSource.setInfoForCategory( minimalCategory, new SuggestionsCategoryInfo(minimalCategory, "Section Title", - ContentSuggestionsCardLayout.MINIMAL_CARD, false, false, - false, true, "No suggestions")); + ContentSuggestionsCardLayout.MINIMAL_CARD, + /* has_fetch_action = */ false, + /* has_view_all_action = */ false, + /* show_if_empty = */ true, "No suggestions")); mSnippetsSource.setStatusForCategory(minimalCategory, CategoryStatus.AVAILABLE); mSnippetsSource.setSuggestionsForCategory( minimalCategory, Arrays.asList(minimalSnippet, minimalSnippet2));
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/ContentSuggestionsTestUtils.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/ContentSuggestionsTestUtils.java index b0f9295..2dcf99b 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/ContentSuggestionsTestUtils.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/ContentSuggestionsTestUtils.java
@@ -47,7 +47,7 @@ @CategoryInt int category, int suggestionCount) { // Important: showIfEmpty flag to true. SuggestionsCategoryInfo categoryInfo = - new CategoryInfoBuilder(category).withReloadAction().showIfEmpty().build(); + new CategoryInfoBuilder(category).withFetchAction().showIfEmpty().build(); return registerCategory(suggestionsSource, categoryInfo, suggestionCount); } @@ -101,9 +101,8 @@ public static class CategoryInfoBuilder { @CategoryInt private final int mCategory; - private boolean mHasMoreAction; + private boolean mHasFetchAction; private boolean mHasViewAllAction; - private boolean mHasReloadAction; private boolean mShowIfEmpty; private String mTitle = ""; private String mNoSuggestionsMessage = ""; @@ -114,8 +113,8 @@ mCategory = category; } - public CategoryInfoBuilder withMoreAction() { - mHasMoreAction = true; + public CategoryInfoBuilder withFetchAction() { + mHasFetchAction = true; return this; } @@ -124,11 +123,6 @@ return this; } - public CategoryInfoBuilder withReloadAction() { - mHasReloadAction = true; - return this; - } - public CategoryInfoBuilder showIfEmpty() { mShowIfEmpty = true; return this; @@ -151,8 +145,8 @@ } public SuggestionsCategoryInfo build() { - return new SuggestionsCategoryInfo(mCategory, mTitle, mCardLayout, mHasMoreAction, - mHasReloadAction, mHasViewAllAction, mShowIfEmpty, mNoSuggestionsMessage); + return new SuggestionsCategoryInfo(mCategory, mTitle, mCardLayout, mHasFetchAction, + mHasViewAllAction, mShowIfEmpty, mNoSuggestionsMessage); } }
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 6cd872f..cc60922 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
@@ -680,30 +680,29 @@ // 0 | Above-the-fold // 1 | Header // 2-4 | Sugg*3 - // 5 | Footer - // 6 | Spacer + // 5 | Action + // 6 | Footer + // 7 | Spacer // Dismiss the second suggestion of the second section. mAdapter.dismissItem(3, itemDismissedCallback); verify(itemDismissedCallback).onResult(anyString()); verify(dataObserver).onItemRangeRemoved(3, 1); - verify(dataObserver).onItemRangeChanged(5, 1, null); + verify(dataObserver).onItemRangeChanged(6, 1, null); // Make sure the call with the updated position works properly. mAdapter.dismissItem(3, itemDismissedCallback); verify(itemDismissedCallback, times(2)).onResult(anyString()); verify(dataObserver, times(2)).onItemRangeRemoved(3, 1); - verify(dataObserver).onItemRangeChanged(4, 1, null); + verify(dataObserver).onItemRangeChanged(5, 1, null); // Dismiss the last suggestion in the section. We should now show the status card. reset(dataObserver); mAdapter.dismissItem(2, itemDismissedCallback); verify(itemDismissedCallback, times(3)).onResult(anyString()); verify(dataObserver).onItemRangeRemoved(2, 1); // Suggestion removed - verify(dataObserver).onItemRangeChanged(3, 1, null); // Spacer refresh - verify(dataObserver).onItemRangeInserted(2, 1); // Status card added verify(dataObserver).onItemRangeChanged(4, 1, null); // Spacer refresh - verify(dataObserver).onItemRangeInserted(3, 1); // Action item added + verify(dataObserver).onItemRangeInserted(2, 1); // Status card added verify(dataObserver).onItemRangeChanged(5, 1, null); // Spacer refresh // Adapter content: @@ -723,9 +722,8 @@ createDummySuggestions(newSuggestionCount, KnownCategories.ARTICLES)); verify(dataObserver).onItemRangeInserted(2, newSuggestionCount); verify(dataObserver).onItemRangeChanged(5 + newSuggestionCount, 1, null); // Spacer refresh - verify(dataObserver, times(2)).onItemRangeRemoved(2 + newSuggestionCount, 1); + verify(dataObserver).onItemRangeRemoved(2 + newSuggestionCount, 1); verify(dataObserver).onItemRangeChanged(4 + newSuggestionCount, 1, null); // Spacer refresh - verify(dataObserver).onItemRangeChanged(3 + newSuggestionCount, 1, null); // Spacer refresh // Adapter content: // Idx | Item @@ -733,8 +731,9 @@ // 0 | Above-the-fold // 1 | Header // 2-8 | Sugg*7 - // 9 | Footer - // 10 | Spacer + // 9 | Action + // 10 | Footer + // 11 | Spacer reset(dataObserver); suggestionsSource.setSuggestionsForCategory( @@ -742,10 +741,8 @@ mAdapter.getSectionListForTesting().onCategoryStatusChanged( KnownCategories.ARTICLES, CategoryStatus.SIGNED_OUT); verify(dataObserver).onItemRangeRemoved(2, newSuggestionCount); - verify(dataObserver).onItemRangeChanged(3, 1, null); // Spacer refresh - verify(dataObserver).onItemRangeInserted(2, 1); // Status card added verify(dataObserver).onItemRangeChanged(4, 1, null); // Spacer refresh - verify(dataObserver).onItemRangeInserted(3, 1); // Action item added + verify(dataObserver).onItemRangeInserted(2, 1); // Status card added verify(dataObserver).onItemRangeChanged(5, 1, null); // Spacer refresh }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java index 3e10559..96db4e3 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java
@@ -93,7 +93,7 @@ @Feature({"Ntp"}) public void testDismissSibling() { List<SnippetArticle> snippets = createDummySuggestions(3, TEST_CATEGORY_ID); - SuggestionsSection section = createSectionWithReloadAction(true); + SuggestionsSection section = createSectionWithFetchAction(true); section.setStatus(CategoryStatus.AVAILABLE); assertNotNull(section.getActionItemForTesting()); @@ -121,7 +121,7 @@ List<SnippetArticle> snippets = createDummySuggestions(suggestionCount, TEST_CATEGORY_ID); - SuggestionsSection section = createSectionWithReloadAction(false); + SuggestionsSection section = createSectionWithFetchAction(false); // Simulate initialisation by the adapter. Here we don't care about the notifications, since // the RecyclerView will be updated through notifyDataSetChanged. section.setStatus(CategoryStatus.AVAILABLE); @@ -141,7 +141,7 @@ final int suggestionCount = 5; List<SnippetArticle> snippets = createDummySuggestions(suggestionCount, TEST_CATEGORY_ID); - SuggestionsSection section = createSectionWithReloadAction(false); + SuggestionsSection section = createSectionWithFetchAction(false); // Simulate initialisation by the adapter. Here we don't care about the notifications, since // the RecyclerView will be updated through notifyDataSetChanged. @@ -168,7 +168,7 @@ @Test @Feature({"Ntp"}) public void testRemoveUnknownSuggestion() { - SuggestionsSection section = createSectionWithReloadAction(false); + SuggestionsSection section = createSectionWithFetchAction(false); section.setStatus(CategoryStatus.AVAILABLE); section.removeSuggestionById("foobar"); } @@ -180,7 +180,7 @@ List<SnippetArticle> snippets = createDummySuggestions(suggestionCount, TEST_CATEGORY_ID); - SuggestionsSection section = createSectionWithReloadAction(false); + SuggestionsSection section = createSectionWithFetchAction(false); section.setStatus(CategoryStatus.AVAILABLE); reset(mParent); @@ -205,11 +205,7 @@ TEST_CATEGORY_ID); SuggestionsCategoryInfo info = - new CategoryInfoBuilder(TEST_CATEGORY_ID) - .withMoreAction() - .withReloadAction() - .showIfEmpty() - .build(); + new CategoryInfoBuilder(TEST_CATEGORY_ID).withFetchAction().showIfEmpty().build(); SuggestionsSection section = createSection(info); section.setStatus(CategoryStatus.AVAILABLE); reset(mParent); @@ -232,7 +228,7 @@ @Test @Feature({"Ntp"}) public void testDismissSection() { - SuggestionsSection section = createSectionWithReloadAction(false); + SuggestionsSection section = createSectionWithFetchAction(false); section.setStatus(CategoryStatus.AVAILABLE); reset(mParent); assertEquals(2, section.getItemCount()); @@ -260,7 +256,7 @@ mBridge.setIsOfflinePageModelLoaded(true); mBridge.setItems(Arrays.asList(item0, item1)); - SuggestionsSection section = createSectionWithReloadAction(true); + SuggestionsSection section = createSectionWithFetchAction(true); section.setSuggestions(snippets, CategoryStatus.AVAILABLE, /* replaceExisting = */ true); // Check that we pick up the correct information. @@ -316,88 +312,29 @@ // When all the actions are enabled, ViewAll always has the priority and is shown. // Spy so that VerifyAction can check methods being called. - SuggestionsCategoryInfo info = - spy(new CategoryInfoBuilder(TEST_CATEGORY_ID) - .withMoreAction() - .withReloadAction() - .withViewAllAction() - .showIfEmpty() - .build()); + SuggestionsCategoryInfo info = spy(new CategoryInfoBuilder(TEST_CATEGORY_ID) + .withFetchAction() + .withViewAllAction() + .showIfEmpty() + .build()); SuggestionsSection section = createSection(info); assertTrue(section.getActionItemForTesting().isVisible()); verifyAction(section, ActionItem.ACTION_VIEW_ALL); - - section.setSuggestions(createDummySuggestions(3, TEST_CATEGORY_ID), - CategoryStatus.AVAILABLE, /* replaceExisting = */ true); - - assertTrue(section.getActionItemForTesting().isVisible()); - verifyAction(section, ActionItem.ACTION_VIEW_ALL); } @Test @Feature({"Ntp"}) - public void testReloadAndFetchMoreActionPriority() { - // When both Reload and FetchMore are enabled, FetchMore runs when we have suggestions, and - // Reload when we don't. - - // Spy so that VerifyAction can check methods being called. - SuggestionsCategoryInfo info = - spy(new CategoryInfoBuilder(TEST_CATEGORY_ID) - .withMoreAction() - .withReloadAction() - .showIfEmpty() - .build()); - SuggestionsSection section = createSection(info); - - assertTrue(section.getActionItemForTesting().isVisible()); - verifyAction(section, ActionItem.ACTION_RELOAD); - - section.setSuggestions(createDummySuggestions(3, TEST_CATEGORY_ID), - CategoryStatus.AVAILABLE, /* replaceExisting = */ true); - - assertTrue(section.getActionItemForTesting().isVisible()); - verifyAction(section, ActionItem.ACTION_FETCH_MORE); - } - - @Test - @Feature({"Ntp"}) - public void testReloadActionPriority() { - // When only Reload is enabled, it only shows when we have no suggestions. + public void testFetchActionPriority() { + // When only FetchMore is shown when enabled. // Spy so that VerifyAction can check methods being called. SuggestionsCategoryInfo info = spy( - new CategoryInfoBuilder(TEST_CATEGORY_ID).withReloadAction().showIfEmpty().build()); + new CategoryInfoBuilder(TEST_CATEGORY_ID).withFetchAction().showIfEmpty().build()); SuggestionsSection section = createSection(info); assertTrue(section.getActionItemForTesting().isVisible()); - verifyAction(section, ActionItem.ACTION_RELOAD); - - section.setSuggestions(createDummySuggestions(3, TEST_CATEGORY_ID), - CategoryStatus.AVAILABLE, /* replaceExisting = */ true); - - assertFalse(section.getActionItemForTesting().isVisible()); - verifyAction(section, ActionItem.ACTION_NONE); - } - - @Test - @Feature({"Ntp"}) - public void testFetchMoreActionPriority() { - // When only FetchMore is enabled, it only shows when we have suggestions. - - // Spy so that VerifyAction can check methods being called. - SuggestionsCategoryInfo info = spy( - new CategoryInfoBuilder(TEST_CATEGORY_ID).withMoreAction().showIfEmpty().build()); - SuggestionsSection section = createSection(info); - - assertFalse(section.getActionItemForTesting().isVisible()); - verifyAction(section, ActionItem.ACTION_NONE); - - section.setSuggestions(createDummySuggestions(3, TEST_CATEGORY_ID), - CategoryStatus.AVAILABLE, /* replaceExisting = */ true); - - assertTrue(section.getActionItemForTesting().isVisible()); - verifyAction(section, ActionItem.ACTION_FETCH_MORE); + verifyAction(section, ActionItem.ACTION_FETCH); } @Test @@ -412,12 +349,6 @@ assertFalse(section.getActionItemForTesting().isVisible()); verifyAction(section, ActionItem.ACTION_NONE); - - section.setSuggestions(createDummySuggestions(3, TEST_CATEGORY_ID), - CategoryStatus.AVAILABLE, /* replaceExisting = */ true); - - assertFalse(section.getActionItemForTesting().isVisible()); - verifyAction(section, ActionItem.ACTION_NONE); } @Test @@ -425,14 +356,14 @@ public void testFetchMoreProgressDisplay() { final int suggestionCount = 3; SuggestionsCategoryInfo info = spy( - new CategoryInfoBuilder(TEST_CATEGORY_ID).withMoreAction().showIfEmpty().build()); + new CategoryInfoBuilder(TEST_CATEGORY_ID).withFetchAction().showIfEmpty().build()); SuggestionsSection section = createSection(info); section.setSuggestions(createDummySuggestions(suggestionCount, TEST_CATEGORY_ID), CategoryStatus.AVAILABLE, /* replaceExisting = */ true); assertFalse(section.getProgressItemForTesting().isVisible()); // Tap the button - verifyAction(section, ActionItem.ACTION_FETCH_MORE); + verifyAction(section, ActionItem.ACTION_FETCH); assertTrue(section.getProgressItemForTesting().isVisible()); // Simulate receiving suggestions. @@ -658,7 +589,7 @@ @Feature({"Ntp"}) public void testCardIsNotifiedWhenBecomingFirst() { List<SnippetArticle> suggestions = createDummySuggestions(5, /* categoryId = */ 42); - SuggestionsSection section = createSectionWithReloadAction(false); + SuggestionsSection section = createSectionWithFetchAction(false); section.setSuggestions(suggestions, CategoryStatus.AVAILABLE, /* replaceExisting = */ true); reset(mParent); @@ -671,7 +602,7 @@ @Feature({"Ntp"}) public void testCardIsNotifiedWhenBecomingLast() { List<SnippetArticle> suggestions = createDummySuggestions(5, /* categoryId = */ 42); - SuggestionsSection section = createSectionWithReloadAction(false); + SuggestionsSection section = createSectionWithFetchAction(false); section.setSuggestions(suggestions, CategoryStatus.AVAILABLE, /* replaceExisting = */ true); reset(mParent); @@ -684,7 +615,7 @@ @Feature({"Ntp"}) public void testCardIsNotifiedWhenBecomingSoleCard() { List<SnippetArticle> suggestions = createDummySuggestions(2, /* categoryId = */ 42); - SuggestionsSection section = createSectionWithReloadAction(false); + SuggestionsSection section = createSectionWithFetchAction(false); section.setSuggestions(suggestions, CategoryStatus.AVAILABLE, /* replaceExisting = */ true); reset(mParent); @@ -697,7 +628,7 @@ @Feature({"Ntp"}) public void testGetItemDismissalGroupWithSuggestions() { List<SnippetArticle> suggestions = createDummySuggestions(5, TEST_CATEGORY_ID); - SuggestionsSection section = createSectionWithReloadAction(false); + SuggestionsSection section = createSectionWithFetchAction(false); section.setSuggestions(suggestions, CategoryStatus.AVAILABLE, /* replaceExisting = */ true); assertThat(section.getItemDismissalGroup(1).size(), is(1)); @@ -707,7 +638,7 @@ @Test @Feature({"Ntp"}) public void testGetItemDismissalGroupWithActionItem() { - SuggestionsSection section = createSectionWithReloadAction(true); + SuggestionsSection section = createSectionWithFetchAction(true); assertThat(section.getItemDismissalGroup(1).size(), is(2)); assertThat(section.getItemDismissalGroup(1), contains(1, 2)); } @@ -715,7 +646,7 @@ @Test @Feature({"Ntp"}) public void testGetItemDismissalGroupWithoutActionItem() { - SuggestionsSection section = createSectionWithReloadAction(false); + SuggestionsSection section = createSectionWithFetchAction(false); assertThat(section.getItemDismissalGroup(1).size(), is(1)); assertThat(section.getItemDismissalGroup(1), contains(1)); } @@ -724,7 +655,7 @@ @Feature({"Ntp"}) public void testCardIsNotifiedWhenNotTheLastAnymore() { List<SnippetArticle> suggestions = createDummySuggestions(5, /* categoryId = */ 42); - SuggestionsSection section = createSectionWithReloadAction(false); + SuggestionsSection section = createSectionWithFetchAction(false); section.setSuggestions(suggestions, CategoryStatus.AVAILABLE, /* replaceExisting = */ true); reset(mParent); @@ -735,7 +666,7 @@ } private SuggestionsSection createSectionWithSuggestions(List<SnippetArticle> snippets) { - SuggestionsSection section = createSectionWithReloadAction(true); + SuggestionsSection section = createSectionWithFetchAction(true); section.setStatus(CategoryStatus.AVAILABLE); section.setSuggestions(snippets, CategoryStatus.AVAILABLE, /* replaceExisting = */ true); @@ -752,9 +683,9 @@ return set; } - private SuggestionsSection createSectionWithReloadAction(boolean hasReloadAction) { + private SuggestionsSection createSectionWithFetchAction(boolean hasReloadAction) { CategoryInfoBuilder builder = new CategoryInfoBuilder(TEST_CATEGORY_ID).showIfEmpty(); - if (hasReloadAction) builder.withReloadAction(); + if (hasReloadAction) builder.withFetchAction(); return createSection(builder.build()); } @@ -784,10 +715,7 @@ verify(section.getCategoryInfo(), (action == ActionItem.ACTION_VIEW_ALL ? times(1) : never())) .performViewAllAction(navDelegate); - verify(suggestionsSource, - action == ActionItem.ACTION_RELOAD || action == ActionItem.ACTION_FETCH_MORE - ? times(1) - : never()) + verify(suggestionsSource, (action == ActionItem.ACTION_FETCH ? times(1) : never())) .fetchSuggestions(anyInt(), any(String[].class)); }
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc index a9c54355..396c6cd 100644 --- a/chrome/app/chrome_main_delegate.cc +++ b/chrome/app/chrome_main_delegate.cc
@@ -977,10 +977,6 @@ // Android doesn't use InitChromeLogging, so we close the log file manually. logging::CloseLogFile(); #endif // !defined(OS_ANDROID) - -#if defined(OS_WIN) - base::debug::RemoveHandleHooks(); -#endif } #if defined(OS_MACOSX)
diff --git a/chrome/browser/PRESUBMIT.py b/chrome/browser/PRESUBMIT.py index 0dbbdae8..0350a06 100644 --- a/chrome/browser/PRESUBMIT.py +++ b/chrome/browser/PRESUBMIT.py
@@ -20,6 +20,23 @@ def CheckChangeOnCommit(input_api, output_api): return _CommonChecks(input_api, output_api) +def _RunHistogramChecks(input_api, output_api, histogram_name): + try: + # Setup sys.path so that we can call histrogram code + import sys + original_sys_path = sys.path + sys.path = sys.path + [input_api.os_path.join( + input_api.change.RepositoryRoot(), + 'tools', 'metrics', 'histograms')] + + import presubmit_bad_message_reasons + return presubmit_bad_message_reasons.PrecheckBadMessage(input_api, + output_api, histogram_name) + except: + return [output_api.PresubmitError('Could not verify histogram!')] + finally: + sys.path = original_sys_path + def _CommonChecks(input_api, output_api): """Checks common to both upload and commit.""" @@ -75,6 +92,8 @@ input_api, output_api, file_filter=is_resource).RunChecks()) results.extend(js_checker.JSChecker( input_api, output_api, file_filter=is_resource).RunChecks()) + results.extend(_RunHistogramChecks(input_api, output_api, + "BadMessageReasonChrome")) finally: sys.path = old_path
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index d9688de..4fd3c68 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1433,12 +1433,6 @@ {"drop-sync-credential", IDS_FLAGS_DROP_SYNC_CREDENTIAL_NAME, IDS_FLAGS_DROP_SYNC_CREDENTIAL_DESCRIPTION, kOsAll, FEATURE_VALUE_TYPE(password_manager::features::kDropSyncCredential)}, -#if BUILDFLAG(ENABLE_EXTENSIONS) - {"enable-extension-action-redesign", - IDS_FLAGS_EXTENSION_ACTION_REDESIGN_NAME, - IDS_FLAGS_EXTENSION_ACTION_REDESIGN_DESCRIPTION, kOsDesktop, - SINGLE_VALUE_TYPE(extensions::switches::kEnableExtensionActionRedesign)}, -#endif // ENABLE_EXTENSIONS #if !defined(OS_ANDROID) {"enable-message-center-always-scroll-up-upon-notification-removal", IDS_FLAGS_MESSAGE_CENTER_ALWAYS_SCROLL_UP_UPON_REMOVAL_NAME,
diff --git a/chrome/browser/android/logo_bridge.cc b/chrome/browser/android/logo_bridge.cc index 5bf6df3..b86e97c9 100644 --- a/chrome/browser/android/logo_bridge.cc +++ b/chrome/browser/android/logo_bridge.cc
@@ -18,6 +18,7 @@ #include "components/search_provider_logos/logo_tracker.h" #include "jni/LogoBridge_jni.h" #include "net/url_request/url_fetcher.h" +#include "net/url_request/url_fetcher_delegate.h" #include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_status.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -173,11 +174,10 @@ LogoBridge::LogoBridge(jobject j_profile) : logo_service_(nullptr), weak_ptr_factory_(this) { Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile); - if (profile) { - logo_service_ = LogoServiceFactory::GetForProfile(profile); - animated_logo_fetcher_ = base::MakeUnique<AnimatedLogoFetcher>( - profile->GetRequestContext()); - } + DCHECK(profile); + logo_service_ = LogoServiceFactory::GetForProfile(profile); + animated_logo_fetcher_ = base::MakeUnique<AnimatedLogoFetcher>( + profile->GetRequestContext()); } LogoBridge::~LogoBridge() {} @@ -189,9 +189,6 @@ void LogoBridge::GetCurrentLogo(JNIEnv* env, const JavaParamRef<jobject>& obj, const JavaParamRef<jobject>& j_logo_observer) { - if (!logo_service_) - return; - // |observer| is deleted in LogoObserverAndroid::OnObserverRemoved(). LogoObserverAndroid* observer = new LogoObserverAndroid( weak_ptr_factory_.GetWeakPtr(), env, j_logo_observer); @@ -202,9 +199,6 @@ const JavaParamRef<jobject>& obj, const JavaParamRef<jobject>& j_callback, const JavaParamRef<jstring>& j_url) { - if (!animated_logo_fetcher_) - return; - GURL url = GURL(ConvertJavaStringToUTF8(env, j_url)); animated_logo_fetcher_->Start(env, url, j_callback); }
diff --git a/chrome/browser/android/logo_bridge.h b/chrome/browser/android/logo_bridge.h index 50a91ee..368a8c3 100644 --- a/chrome/browser/android/logo_bridge.h +++ b/chrome/browser/android/logo_bridge.h
@@ -10,7 +10,6 @@ #include "base/android/scoped_java_ref.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "net/url_request/url_fetcher_delegate.h" class LogoService;
diff --git a/chrome/browser/android/ntp/ntp_snippets_bridge.cc b/chrome/browser/android/ntp/ntp_snippets_bridge.cc index c275945..3389af1 100644 --- a/chrome/browser/android/ntp/ntp_snippets_bridge.cc +++ b/chrome/browser/android/ntp/ntp_snippets_bridge.cc
@@ -202,9 +202,8 @@ } return Java_SnippetsBridge_createSuggestionsCategoryInfo( env, j_category_id, ConvertUTF16ToJavaString(env, info->title()), - static_cast<int>(info->card_layout()), info->has_more_action(), - info->has_reload_action(), info->has_view_all_action(), - info->show_if_empty(), + static_cast<int>(info->card_layout()), info->has_fetch_action(), + info->has_view_all_action(), info->show_if_empty(), ConvertUTF16ToJavaString(env, info->no_suggestions_message())); }
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn index 49258430..eac0680 100644 --- a/chrome/browser/extensions/BUILD.gn +++ b/chrome/browser/extensions/BUILD.gn
@@ -238,6 +238,8 @@ "api/identity/identity_api.h", "api/identity/identity_constants.cc", "api/identity/identity_constants.h", + "api/identity/identity_get_profile_user_info_function.cc", + "api/identity/identity_get_profile_user_info_function.h", "api/identity/identity_launch_web_auth_flow_function.cc", "api/identity/identity_launch_web_auth_flow_function.h", "api/identity/identity_mint_queue.cc",
diff --git a/chrome/browser/extensions/api/identity/identity_api.cc b/chrome/browser/extensions/api/identity/identity_api.cc index 81d003ea3..f0ee2195 100644 --- a/chrome/browser/extensions/api/identity/identity_api.cc +++ b/chrome/browser/extensions/api/identity/identity_api.cc
@@ -880,28 +880,4 @@ return client_id; } -IdentityGetProfileUserInfoFunction::IdentityGetProfileUserInfoFunction() { -} - -IdentityGetProfileUserInfoFunction::~IdentityGetProfileUserInfoFunction() { -} - -ExtensionFunction::ResponseAction IdentityGetProfileUserInfoFunction::Run() { - if (GetProfile()->IsOffTheRecord()) { - return RespondNow(Error(identity_constants::kOffTheRecord)); - } - - AccountInfo account = - AccountTrackerServiceFactory::GetForProfile(GetProfile()) - ->GetAccountInfo(GetPrimaryAccountId(GetProfile())); - api::identity::ProfileUserInfo profile_user_info; - if (extension()->permissions_data()->HasAPIPermission( - APIPermission::kIdentityEmail)) { - profile_user_info.email = account.email; - profile_user_info.id = account.gaia; - } - - return RespondNow(OneArgument(profile_user_info.ToValue())); -} - } // namespace extensions
diff --git a/chrome/browser/extensions/api/identity/identity_api.h b/chrome/browser/extensions/api/identity/identity_api.h index b39ae41..66599fc 100644 --- a/chrome/browser/extensions/api/identity/identity_api.h +++ b/chrome/browser/extensions/api/identity/identity_api.h
@@ -18,6 +18,7 @@ #include "build/build_config.h" #include "chrome/browser/extensions/api/identity/extension_token_key.h" #include "chrome/browser/extensions/api/identity/gaia_web_auth_flow.h" +#include "chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.h" #include "chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.h" #include "chrome/browser/extensions/api/identity/identity_mint_queue.h" #include "chrome/browser/extensions/api/identity/identity_remove_cached_auth_token_function.h" @@ -291,21 +292,6 @@ std::unique_ptr<IdentitySigninFlow> signin_flow_; }; -class IdentityGetProfileUserInfoFunction - : public ChromeUIThreadExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("identity.getProfileUserInfo", - IDENTITY_GETPROFILEUSERINFO); - - IdentityGetProfileUserInfoFunction(); - - private: - ~IdentityGetProfileUserInfoFunction() override; - - // UIThreadExtensionFunction implementation. - ExtensionFunction::ResponseAction Run() override; -}; - } // namespace extensions #endif // CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_API_H_
diff --git a/chrome/browser/extensions/api/identity/identity_apitest.cc b/chrome/browser/extensions/api/identity/identity_apitest.cc index 8948254..a652c4b 100644 --- a/chrome/browser/extensions/api/identity/identity_apitest.cc +++ b/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -23,6 +23,7 @@ #endif #include "chrome/browser/extensions/api/identity/identity_api.h" #include "chrome/browser/extensions/api/identity/identity_constants.h" +#include "chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.h" #include "chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.h" #include "chrome/browser/extensions/api/identity/identity_remove_cached_auth_token_function.h" #include "chrome/browser/extensions/component_loader.h"
diff --git a/chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.cc b/chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.cc new file mode 100644 index 0000000..09405866 --- /dev/null +++ b/chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.cc
@@ -0,0 +1,40 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.h" + +#include "chrome/browser/extensions/api/identity/identity_constants.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/signin_manager_factory.h" +#include "chrome/common/extensions/api/identity.h" +#include "components/signin/core/browser/signin_manager.h" +#include "extensions/common/extension.h" +#include "extensions/common/permissions/permissions_data.h" + +namespace extensions { + +IdentityGetProfileUserInfoFunction::IdentityGetProfileUserInfoFunction() { +} + +IdentityGetProfileUserInfoFunction::~IdentityGetProfileUserInfoFunction() { +} + +ExtensionFunction::ResponseAction IdentityGetProfileUserInfoFunction::Run() { + if (GetProfile()->IsOffTheRecord()) { + return RespondNow(Error(identity_constants::kOffTheRecord)); + } + + AccountInfo account = SigninManagerFactory::GetForProfile( + GetProfile())->GetAuthenticatedAccountInfo(); + api::identity::ProfileUserInfo profile_user_info; + if (extension()->permissions_data()->HasAPIPermission( + APIPermission::kIdentityEmail)) { + profile_user_info.email = account.email; + profile_user_info.id = account.gaia; + } + + return RespondNow(OneArgument(profile_user_info.ToValue())); +} + +} // namespace extensions
diff --git a/chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.h b/chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.h new file mode 100644 index 0000000..2d3b434 --- /dev/null +++ b/chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.h
@@ -0,0 +1,30 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_GET_PROFILE_USER_INFO_FUNCTION_H_ +#define CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_GET_PROFILE_USER_INFO_FUNCTION_H_ + +#include "chrome/browser/extensions/chrome_extension_function.h" +#include "extensions/browser/extension_function_histogram_value.h" + +namespace extensions { + +class IdentityGetProfileUserInfoFunction + : public ChromeUIThreadExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("identity.getProfileUserInfo", + IDENTITY_GETPROFILEUSERINFO); + + IdentityGetProfileUserInfoFunction(); + + private: + ~IdentityGetProfileUserInfoFunction() override; + + // UIThreadExtensionFunction implementation. + ExtensionFunction::ResponseAction Run() override; +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_GET_PROFILE_USER_INFO_FUNCTION_H_
diff --git a/chrome/browser/extensions/dev_mode_bubble_delegate.cc b/chrome/browser/extensions/dev_mode_bubble_delegate.cc index e838351e..d23784e 100644 --- a/chrome/browser/extensions/dev_mode_bubble_delegate.cc +++ b/chrome/browser/extensions/dev_mode_bubble_delegate.cc
@@ -74,6 +74,10 @@ return false; } +bool DevModeBubbleDelegate::ShouldAcknowledgeOnDeactivate() const { + return false; +} + bool DevModeBubbleDelegate::ShouldShowExtensionList() const { return false; }
diff --git a/chrome/browser/extensions/dev_mode_bubble_delegate.h b/chrome/browser/extensions/dev_mode_bubble_delegate.h index a79a2a0..2f34d52 100644 --- a/chrome/browser/extensions/dev_mode_bubble_delegate.h +++ b/chrome/browser/extensions/dev_mode_bubble_delegate.h
@@ -37,6 +37,7 @@ base::string16 GetActionButtonLabel() const override; base::string16 GetDismissButtonLabel() const override; bool ShouldCloseOnDeactivate() const override; + bool ShouldAcknowledgeOnDeactivate() const override; bool ShouldShowExtensionList() const override; bool ShouldHighlightExtensions() const override; bool ShouldLimitToEnabledExtensions() const override;
diff --git a/chrome/browser/extensions/extension_action_runner.cc b/chrome/browser/extensions/extension_action_runner.cc index fdf670b64..e3590c1 100644 --- a/chrome/browser/extensions/extension_action_runner.cc +++ b/chrome/browser/extensions/extension_action_runner.cc
@@ -30,8 +30,8 @@ #include "chrome/common/extensions/api/extension_action/action_info.h" #include "components/crx_file/id_util.h" #include "content/public/browser/navigation_controller.h" -#include "content/public/browser/navigation_details.h" #include "content/public/browser/navigation_entry.h" +#include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" #include "extensions/browser/extension_registry.h" @@ -399,11 +399,13 @@ return handled; } -void ExtensionActionRunner::DidNavigateMainFrame( - const content::LoadCommittedDetails& details, - const content::FrameNavigateParams& params) { - if (details.is_in_page) +void ExtensionActionRunner::DidFinishNavigation( + content::NavigationHandle* navigation_handle) { + if (!navigation_handle->IsInMainFrame() || + !navigation_handle->HasCommitted() || + navigation_handle->IsSamePage()) { return; + } LogUMA(); num_page_requests_ = 0;
diff --git a/chrome/browser/extensions/extension_action_runner.h b/chrome/browser/extensions/extension_action_runner.h index 16e90970..a7ab6e3e 100644 --- a/chrome/browser/extensions/extension_action_runner.h +++ b/chrome/browser/extensions/extension_action_runner.h
@@ -164,9 +164,8 @@ // content::WebContentsObserver implementation. bool OnMessageReceived(const IPC::Message& message, content::RenderFrameHost* render_frame_host) override; - void DidNavigateMainFrame( - const content::LoadCommittedDetails& details, - const content::FrameNavigateParams& params) override; + void DidFinishNavigation( + content::NavigationHandle* navigation_handle) override; // ExtensionRegistryObserver: void OnExtensionUnloaded(content::BrowserContext* browser_context,
diff --git a/chrome/browser/extensions/extension_message_bubble_controller.cc b/chrome/browser/extensions/extension_message_bubble_controller.cc index 15ea349a..96fda8c 100644 --- a/chrome/browser/extensions/extension_message_bubble_controller.cc +++ b/chrome/browser/extensions/extension_message_bubble_controller.cc
@@ -316,7 +316,8 @@ // If the bubble was closed due to deactivation, don't treat it as // acknowledgment so that the user will see the bubble again (until they // explicitly take an action). - if (user_action_ != ACTION_DISMISS_DEACTIVATION) { + if (user_action_ != ACTION_DISMISS_DEACTIVATION || + delegate_->ShouldAcknowledgeOnDeactivate()) { AcknowledgeExtensions(); if (delegate_->ClearProfileSetAfterAction()) GetProfileSet()->clear();
diff --git a/chrome/browser/extensions/extension_message_bubble_controller.h b/chrome/browser/extensions/extension_message_bubble_controller.h index 0bd63a5..53a13a7 100644 --- a/chrome/browser/extensions/extension_message_bubble_controller.h +++ b/chrome/browser/extensions/extension_message_bubble_controller.h
@@ -68,6 +68,10 @@ // Returns true if the bubble should close when the widget deactivates. virtual bool ShouldCloseOnDeactivate() const = 0; + // Returns true if the bubble should be considered acknowledged when the + // widget deactivates. + virtual bool ShouldAcknowledgeOnDeactivate() const = 0; + // Whether to show a list of extensions in the bubble. virtual bool ShouldShowExtensionList() const = 0;
diff --git a/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc b/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc index 90db931..c599ff74 100644 --- a/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc +++ b/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc
@@ -14,6 +14,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "base/values.h" #include "build/build_config.h" #include "chrome/browser/extensions/dev_mode_bubble_delegate.h" @@ -28,6 +29,7 @@ #include "chrome/browser/extensions/test_extension_system.h" #include "chrome/browser/ui/toolbar/toolbar_actions_model.h" #include "chrome/browser/ui/toolbar/toolbar_actions_model_factory.h" +#include "chrome/common/chrome_features.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/testing_profile.h" #include "components/proxy_config/proxy_config_pref_names.h" @@ -359,7 +361,25 @@ DISALLOW_COPY_AND_ASSIGN(ExtensionMessageBubbleTest); }; -TEST_F(ExtensionMessageBubbleTest, BubbleReshowsOnDeactivationDismissal) { +class ExtensionMessageBubbleTestWithParam + : public ExtensionMessageBubbleTest, + public ::testing::WithParamInterface<bool> {}; + +// Test that the bubble correctly treats dismissal due to deactivation. +// Currently, the NTP bubble is the only one that has flexible behavior (toggled +// by a feature). +TEST_P(ExtensionMessageBubbleTestWithParam, + BubbleCorrectlyReshowsOnDeactivationDismissal) { + const bool kAcknowledgeOnDeactivate = GetParam(); + base::test::ScopedFeatureList feature_list; + if (kAcknowledgeOnDeactivate) { + feature_list.InitAndEnableFeature( + features::kAcknowledgeNtpOverrideOnDeactivate); + } else { + feature_list.InitAndDisableFeature( + features::kAcknowledgeNtpOverrideOnDeactivate); + } + Init(); ASSERT_TRUE(LoadExtensionOverridingNtp("1", kId1, Manifest::INTERNAL)); @@ -392,39 +412,54 @@ // No extension should have become disabled. ExtensionRegistry* registry = ExtensionRegistry::Get(profile()); EXPECT_TRUE(registry->enabled_extensions().GetByID(kId2)); - // And since it was dismissed due to deactivation, the extension should not - // have been acknowledged. - EXPECT_FALSE(controller->delegate()->HasBubbleInfoBeenAcknowledged(kId2)); - bubble.set_action_on_show( - FakeExtensionMessageBubble::BUBBLE_ACTION_DISMISS_DEACTIVATION); - controller.reset(new TestExtensionMessageBubbleController( - new NtpOverriddenBubbleDelegate(browser()->profile()), browser())); - controller->SetIsActiveBubble(); - // The bubble shouldn't show again for the same profile (we don't want to - // be annoying). - EXPECT_FALSE(controller->ShouldShow()); - controller->ClearProfileListForTesting(); - EXPECT_TRUE(controller->ShouldShow()); - // Explicitly click the dismiss button. The extension should be acknowledged. - bubble.set_controller(controller.get()); - bubble.set_action_on_show( - FakeExtensionMessageBubble::BUBBLE_ACTION_CLICK_DISMISS_BUTTON); - bubble.Show(); - EXPECT_TRUE(controller->delegate()->HasBubbleInfoBeenAcknowledged(kId2)); + if (kAcknowledgeOnDeactivate) { + EXPECT_TRUE(controller->delegate()->HasBubbleInfoBeenAcknowledged(kId2)); + + controller.reset(new TestExtensionMessageBubbleController( + new ProxyOverriddenBubbleDelegate(browser()->profile()), browser())); + controller->ClearProfileListForTesting(); + controller->SetIsActiveBubble(); + EXPECT_FALSE(controller->ShouldShow()); + } else { + // Since the bubble was dismissed due to deactivation, the extension should + // not have been acknowledged. + EXPECT_FALSE(controller->delegate()->HasBubbleInfoBeenAcknowledged(kId2)); + + bubble.set_action_on_show( + FakeExtensionMessageBubble::BUBBLE_ACTION_DISMISS_DEACTIVATION); + controller.reset(new TestExtensionMessageBubbleController( + new NtpOverriddenBubbleDelegate(browser()->profile()), browser())); + controller->SetIsActiveBubble(); + // The bubble shouldn't show again for the same profile (we don't want to + // be annoying). + EXPECT_FALSE(controller->ShouldShow()); + controller->ClearProfileListForTesting(); + EXPECT_TRUE(controller->ShouldShow()); + // Explicitly click the dismiss button. The extension should be + // acknowledged. + bubble.set_controller(controller.get()); + bubble.set_action_on_show( + FakeExtensionMessageBubble::BUBBLE_ACTION_CLICK_DISMISS_BUTTON); + bubble.Show(); + EXPECT_TRUE(controller->delegate()->HasBubbleInfoBeenAcknowledged(kId2)); + } // Uninstall the current ntp-controlling extension, allowing the other to // take control. service_->UninstallExtension(kId2, UNINSTALL_REASON_FOR_TESTING, base::Bind(&base::DoNothing), nullptr); - // Even though we already showed for the given profile, we should show again, - // because it's a different extension. + // Even though we already showed for the given profile, we should show + // again, because it's a different extension. controller.reset(new TestExtensionMessageBubbleController( new NtpOverriddenBubbleDelegate(browser()->profile()), browser())); EXPECT_TRUE(controller->ShouldShow()); } +INSTANTIATE_TEST_CASE_P(ExtensionMessageBubbleTest, + ExtensionMessageBubbleTestWithParam, testing::Bool()); + // The feature this is meant to test is only enacted on Windows, but it should // pass on all platforms. TEST_F(ExtensionMessageBubbleTest, WipeoutControllerTest) {
diff --git a/chrome/browser/extensions/installed_loader.cc b/chrome/browser/extensions/installed_loader.cc index 70d4111..4f3cf1b 100644 --- a/chrome/browser/extensions/installed_loader.cc +++ b/chrome/browser/extensions/installed_loader.cc
@@ -355,6 +355,7 @@ int file_access_allowed_count = 0; int file_access_not_allowed_count = 0; int eventless_event_pages_count = 0; + int off_store_item_count = 0; const ExtensionSet& extensions = extension_registry_->enabled_extensions(); for (ExtensionSet::const_iterator iter = extensions.begin(); @@ -527,6 +528,9 @@ ++file_access_not_allowed_count; } } + + if (!ManifestURL::UpdatesFromGallery(extension)) + ++off_store_item_count; } const ExtensionSet& disabled_extensions = @@ -615,6 +619,8 @@ extension_prefs_->GetCorruptedDisableCount()); UMA_HISTOGRAM_COUNTS_100("Extensions.EventlessEventPages", eventless_event_pages_count); + UMA_HISTOGRAM_COUNTS_100("Extensions.LoadOffStoreItems", + off_store_item_count); } int InstalledLoader::GetCreationFlags(const ExtensionInfo* info) {
diff --git a/chrome/browser/extensions/ntp_overridden_bubble_delegate.cc b/chrome/browser/extensions/ntp_overridden_bubble_delegate.cc index 5e96f0a..177dcae 100644 --- a/chrome/browser/extensions/ntp_overridden_bubble_delegate.cc +++ b/chrome/browser/extensions/ntp_overridden_bubble_delegate.cc
@@ -4,11 +4,13 @@ #include "chrome/browser/extensions/ntp_overridden_bubble_delegate.h" +#include "base/feature_list.h" #include "base/metrics/histogram_macros.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_web_ui.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/url_constants.h" #include "chrome/grit/generated_resources.h" #include "extensions/browser/extension_registry.h" @@ -105,6 +107,11 @@ return true; } +bool NtpOverriddenBubbleDelegate::ShouldAcknowledgeOnDeactivate() const { + return base::FeatureList::IsEnabled( + features::kAcknowledgeNtpOverrideOnDeactivate); +} + bool NtpOverriddenBubbleDelegate::ShouldShowExtensionList() const { return false; }
diff --git a/chrome/browser/extensions/ntp_overridden_bubble_delegate.h b/chrome/browser/extensions/ntp_overridden_bubble_delegate.h index 1845c79..15d0911 100644 --- a/chrome/browser/extensions/ntp_overridden_bubble_delegate.h +++ b/chrome/browser/extensions/ntp_overridden_bubble_delegate.h
@@ -36,6 +36,7 @@ base::string16 GetActionButtonLabel() const override; base::string16 GetDismissButtonLabel() const override; bool ShouldCloseOnDeactivate() const override; + bool ShouldAcknowledgeOnDeactivate() const override; bool ShouldShowExtensionList() const override; bool ShouldHighlightExtensions() const override; bool ShouldLimitToEnabledExtensions() const override;
diff --git a/chrome/browser/extensions/proxy_overridden_bubble_delegate.cc b/chrome/browser/extensions/proxy_overridden_bubble_delegate.cc index afb2e0f7..1d05de2 100644 --- a/chrome/browser/extensions/proxy_overridden_bubble_delegate.cc +++ b/chrome/browser/extensions/proxy_overridden_bubble_delegate.cc
@@ -120,6 +120,10 @@ return false; } +bool ProxyOverriddenBubbleDelegate::ShouldAcknowledgeOnDeactivate() const { + return false; +} + bool ProxyOverriddenBubbleDelegate::ShouldShowExtensionList() const { return false; }
diff --git a/chrome/browser/extensions/proxy_overridden_bubble_delegate.h b/chrome/browser/extensions/proxy_overridden_bubble_delegate.h index da36b2e0..7c254d65 100644 --- a/chrome/browser/extensions/proxy_overridden_bubble_delegate.h +++ b/chrome/browser/extensions/proxy_overridden_bubble_delegate.h
@@ -35,6 +35,7 @@ base::string16 GetActionButtonLabel() const override; base::string16 GetDismissButtonLabel() const override; bool ShouldCloseOnDeactivate() const override; + bool ShouldAcknowledgeOnDeactivate() const override; bool ShouldShowExtensionList() const override; bool ShouldHighlightExtensions() const override; bool ShouldLimitToEnabledExtensions() const override;
diff --git a/chrome/browser/extensions/settings_api_bubble_delegate.cc b/chrome/browser/extensions/settings_api_bubble_delegate.cc index c60ce7f..8fb398e 100644 --- a/chrome/browser/extensions/settings_api_bubble_delegate.cc +++ b/chrome/browser/extensions/settings_api_bubble_delegate.cc
@@ -199,6 +199,10 @@ return type_ != BUBBLE_TYPE_STARTUP_PAGES; } +bool SettingsApiBubbleDelegate::ShouldAcknowledgeOnDeactivate() const { + return false; +} + bool SettingsApiBubbleDelegate::ShouldShowExtensionList() const { return false; }
diff --git a/chrome/browser/extensions/settings_api_bubble_delegate.h b/chrome/browser/extensions/settings_api_bubble_delegate.h index 737fa58..9e36bd46 100644 --- a/chrome/browser/extensions/settings_api_bubble_delegate.h +++ b/chrome/browser/extensions/settings_api_bubble_delegate.h
@@ -36,6 +36,7 @@ base::string16 GetActionButtonLabel() const override; base::string16 GetDismissButtonLabel() const override; bool ShouldCloseOnDeactivate() const override; + bool ShouldAcknowledgeOnDeactivate() const override; bool ShouldShowExtensionList() const override; bool ShouldHighlightExtensions() const override; bool ShouldLimitToEnabledExtensions() const override;
diff --git a/chrome/browser/extensions/suspicious_extension_bubble_delegate.cc b/chrome/browser/extensions/suspicious_extension_bubble_delegate.cc index 931fc750..504c937 100644 --- a/chrome/browser/extensions/suspicious_extension_bubble_delegate.cc +++ b/chrome/browser/extensions/suspicious_extension_bubble_delegate.cc
@@ -104,6 +104,10 @@ return false; } +bool SuspiciousExtensionBubbleDelegate::ShouldAcknowledgeOnDeactivate() const { + return false; +} + bool SuspiciousExtensionBubbleDelegate::ShouldShowExtensionList() const { return true; }
diff --git a/chrome/browser/extensions/suspicious_extension_bubble_delegate.h b/chrome/browser/extensions/suspicious_extension_bubble_delegate.h index d36f500..016e0e38 100644 --- a/chrome/browser/extensions/suspicious_extension_bubble_delegate.h +++ b/chrome/browser/extensions/suspicious_extension_bubble_delegate.h
@@ -33,6 +33,7 @@ base::string16 GetActionButtonLabel() const override; base::string16 GetDismissButtonLabel() const override; bool ShouldCloseOnDeactivate() const override; + bool ShouldAcknowledgeOnDeactivate() const override; bool ShouldShowExtensionList() const override; bool ShouldHighlightExtensions() const override; bool ShouldLimitToEnabledExtensions() const override;
diff --git a/chrome/browser/ntp_snippets/download_suggestions_provider.cc b/chrome/browser/ntp_snippets/download_suggestions_provider.cc index 9eb137b..2b43b4eb 100644 --- a/chrome/browser/ntp_snippets/download_suggestions_provider.cc +++ b/chrome/browser/ntp_snippets/download_suggestions_provider.cc
@@ -188,8 +188,7 @@ return CategoryInfo( l10n_util::GetStringUTF16(IDS_NTP_DOWNLOAD_SUGGESTIONS_SECTION_HEADER), ntp_snippets::ContentSuggestionsCardLayout::MINIMAL_CARD, - /*has_more_action=*/false, - /*has_reload_action=*/false, + /*has_fetch_action=*/false, /*has_view_all_action=*/true, /*show_if_empty=*/false, l10n_util::GetStringUTF16(IDS_NTP_DOWNLOADS_SUGGESTIONS_SECTION_EMPTY));
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc index 9c577fa..141e2aa5 100644 --- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc +++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -64,6 +64,7 @@ #include "chrome/browser/themes/theme_service_factory.h" #include "chrome/browser/thumbnails/thumbnail_service_factory.h" #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h" +#include "chrome/browser/ui/desktop_ios_promotion/sms_service_factory.h" #include "chrome/browser/ui/find_bar/find_bar_state_factory.h" #include "chrome/browser/ui/prefs/prefs_tab_helper.h" #include "chrome/browser/ui/tabs/pinned_tab_service_factory.h" @@ -223,6 +224,9 @@ #endif NotifierStateTrackerFactory::GetInstance(); data_use_measurement::ChromeDataUseAscriberServiceFactory::GetInstance(); +#if !defined(OS_ANDROID) + SMSServiceFactory::GetInstance(); +#endif dom_distiller::DomDistillerServiceFactory::GetInstance(); domain_reliability::DomainReliabilityServiceFactory::GetInstance(); DownloadServiceFactory::GetInstance();
diff --git a/chrome/browser/sync/test/integration/sync_errors_test.cc b/chrome/browser/sync/test/integration/sync_errors_test.cc index cce9867..961af28 100644 --- a/chrome/browser/sync/test/integration/sync_errors_test.cc +++ b/chrome/browser/sync/test/integration/sync_errors_test.cc
@@ -202,7 +202,13 @@ // Tests that on receiving CLIENT_DATA_OBSOLETE sync engine gets restarted and // initialized with different cache_guld. -IN_PROC_BROWSER_TEST_F(SyncErrorTest, ClientDataObsoleteTest) { +// Flaky on Windows and Linux. See crbug.com/683216 +#if defined(OS_WIN) || defined(OS_LINUX) +#define MAYBE_ClientDataObsoleteTest DISABLED_ClientDataObsoleteTest +#else +#define MAYBE_ClientDataObsoleteTest ClientDataObsoleteTest +#endif +IN_PROC_BROWSER_TEST_F(SyncErrorTest, MAYBE_ClientDataObsoleteTest) { ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; const BookmarkNode* node1 = AddFolder(0, 0, "title1");
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 712efa6..35f819a6 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -717,6 +717,10 @@ "desktop_ios_promotion/desktop_ios_promotion_controller.h", "desktop_ios_promotion/desktop_ios_promotion_util.cc", "desktop_ios_promotion/desktop_ios_promotion_util.h", + "desktop_ios_promotion/sms_service.cc", + "desktop_ios_promotion/sms_service.h", + "desktop_ios_promotion/sms_service_factory.cc", + "desktop_ios_promotion/sms_service_factory.h", "exclusive_access/exclusive_access_bubble.cc", "exclusive_access/exclusive_access_bubble.h", "exclusive_access/exclusive_access_bubble_type.cc",
diff --git a/chrome/browser/ui/desktop_ios_promotion/sms_service.cc b/chrome/browser/ui/desktop_ios_promotion/sms_service.cc new file mode 100644 index 0000000..0a79da9 --- /dev/null +++ b/chrome/browser/ui/desktop_ios_promotion/sms_service.cc
@@ -0,0 +1,314 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/desktop_ios_promotion/sms_service.h" + +#include "base/bind.h" +#include "base/json/json_reader.h" +#include "base/memory/ptr_util.h" +#include "base/metrics/histogram_macros.h" +#include "base/optional.h" +#include "base/strings/stringprintf.h" +#include "components/signin/core/browser/signin_manager.h" +#include "google_apis/gaia/gaia_urls.h" +#include "google_apis/gaia/oauth2_token_service.h" +#include "net/base/load_flags.h" +#include "net/base/url_util.h" +#include "net/http/http_status_code.h" +#include "net/http/http_util.h" +#include "net/url_request/url_fetcher.h" +#include "net/url_request/url_fetcher_delegate.h" +#include "net/url_request/url_request_context_getter.h" + +namespace { + +const char kDesktopIOSPromotionOAuthScope[] = + "https://www.googleapis.com/auth/mobile_user_preferences"; + +const char kDesktopIOSPromotionQueryPhoneNumber[] = + "https://growth-pa.googleapis.com/v1/get_verified_phone_numbers"; + +const char kDesktopIOSPromotionSendSMS[] = + "https://growth-pa.googleapis.com/v1/send_sms"; + +const char kPostDataMimeType[] = "application/json"; + +const char kSendSMSPromoFormat[] = "{promo_id:%s}"; + +// The maximum number of retries for the URLFetcher requests. +const size_t kMaxRetries = 1; + +class RequestImpl : public SMSService::Request, + private OAuth2TokenService::Consumer, + private net::URLFetcherDelegate { + public: + ~RequestImpl() override {} + + // Returns the response code received from the server, which will only be + // valid if the request succeeded. + int GetResponseCode() override { return response_code_; } + + // Returns the contents of the response body received from the server. + const std::string& GetResponseBody() override { return response_body_; } + + bool IsPending() override { return is_pending_; } + + private: + friend class ::SMSService; + + RequestImpl( + OAuth2TokenService* token_service, + SigninManagerBase* signin_manager, + const scoped_refptr<net::URLRequestContextGetter>& request_context, + const GURL& url, + const SMSService::CompletionCallback& callback) + : OAuth2TokenService::Consumer("desktop_ios_promotion"), + token_service_(token_service), + signin_manager_(signin_manager), + request_context_(request_context), + url_(url), + post_data_mime_type_(kPostDataMimeType), + response_code_(0), + auth_retry_count_(0), + callback_(callback), + is_pending_(false) { + DCHECK(token_service_); + DCHECK(signin_manager_); + DCHECK(request_context_); + } + + void Start() override { + OAuth2TokenService::ScopeSet oauth_scopes; + oauth_scopes.insert(kDesktopIOSPromotionOAuthScope); + token_request_ = token_service_->StartRequest( + signin_manager_->GetAuthenticatedAccountId(), oauth_scopes, this); + is_pending_ = true; + } + + // content::URLFetcherDelegate interface. + void OnURLFetchComplete(const net::URLFetcher* source) override { + DCHECK_EQ(source, url_fetcher_.get()); + response_code_ = url_fetcher_->GetResponseCode(); + + UMA_HISTOGRAM_CUSTOM_ENUMERATION( + "DesktopIOSPromotion.OAuthTokenResponseCode", + net::HttpUtil::MapStatusCodeForHistogram(response_code_), + net::HttpUtil::GetStatusCodesForHistogram()); + + // If the response code indicates that the token might not be valid, + // invalidate the token and try again. + if (response_code_ == net::HTTP_UNAUTHORIZED && ++auth_retry_count_ <= 1) { + OAuth2TokenService::ScopeSet oauth_scopes; + oauth_scopes.insert(kDesktopIOSPromotionOAuthScope); + token_service_->InvalidateAccessToken( + signin_manager_->GetAuthenticatedAccountId(), oauth_scopes, + access_token_); + + access_token_.clear(); + Start(); + return; + } + url_fetcher_->GetResponseAsString(&response_body_); + url_fetcher_.reset(); + is_pending_ = false; + callback_.Run(this, response_code_ == net::HTTP_OK); + // It is valid for the callback to delete |this|, so do not access any + // members below here. + } + + // OAuth2TokenService::Consumer interface. + void OnGetTokenSuccess(const OAuth2TokenService::Request* request, + const std::string& access_token, + const base::Time& expiration_time) override { + token_request_.reset(); + DCHECK(!access_token.empty()); + access_token_ = access_token; + + UMA_HISTOGRAM_BOOLEAN("DesktopIOSPromotion.OAuthTokenCompletion", true); + + // Got an access token -- start the actual API request. + url_fetcher_ = CreateUrlFetcher(access_token); + url_fetcher_->Start(); + } + + void OnGetTokenFailure(const OAuth2TokenService::Request* request, + const GoogleServiceAuthError& error) override { + token_request_.reset(); + is_pending_ = false; + + UMA_HISTOGRAM_BOOLEAN("DesktopIOSPromotion.OAuthTokenCompletion", false); + + callback_.Run(this, false); + // It is valid for the callback to delete |this|, so do not access any + // members below here. + } + + // Helper for creating a new URLFetcher for the API request. + std::unique_ptr<net::URLFetcher> CreateUrlFetcher( + const std::string& access_token) { + net::URLFetcher::RequestType request_type = + post_data_ ? net::URLFetcher::POST : net::URLFetcher::GET; + std::unique_ptr<net::URLFetcher> fetcher = + net::URLFetcher::Create(url_, request_type, this); + fetcher->SetRequestContext(request_context_.get()); + fetcher->SetMaxRetriesOn5xx(kMaxRetries); + fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | + net::LOAD_DO_NOT_SAVE_COOKIES); + fetcher->AddExtraRequestHeader("Authorization: Bearer " + access_token); + fetcher->AddExtraRequestHeader( + "X-Developer-Key: " + + GaiaUrls::GetInstance()->oauth2_chrome_client_id()); + + if (post_data_) + fetcher->SetUploadData(post_data_mime_type_, post_data_.value()); + return fetcher; + } + + void SetPostData(const std::string& post_data) override { + SetPostDataAndType(post_data, kPostDataMimeType); + } + + void SetPostDataAndType(const std::string& post_data, + const std::string& mime_type) override { + post_data_ = post_data; + post_data_mime_type_ = mime_type; + } + + OAuth2TokenService* token_service_; + SigninManagerBase* signin_manager_; + scoped_refptr<net::URLRequestContextGetter> request_context_; + + // The URL of the API endpoint. + GURL url_; + + // POST data to be sent with the request (may be empty). + base::Optional<std::string> post_data_; + + // MIME type of the post requests. Defaults to text/plain. + std::string post_data_mime_type_; + + // The OAuth2 access token request. + std::unique_ptr<OAuth2TokenService::Request> token_request_; + + // The current OAuth2 access token. + std::string access_token_; + + // Handles the actual API requests after the OAuth token is acquired. + std::unique_ptr<net::URLFetcher> url_fetcher_; + + // Holds the response code received from the server. + int response_code_; + + // Holds the response body received from the server. + std::string response_body_; + + // The number of times this request has already been retried due to + // authorization problems. + int auth_retry_count_; + + // The callback to execute when the query is complete. + SMSService::CompletionCallback callback_; + + // True if the request was started and has not yet completed, otherwise false. + bool is_pending_; +}; + +} // namespace + +SMSService::Request::Request() {} + +SMSService::Request::~Request() {} + +SMSService::SMSService( + OAuth2TokenService* token_service, + SigninManagerBase* signin_manager, + const scoped_refptr<net::URLRequestContextGetter>& request_context) + : token_service_(token_service), + signin_manager_(signin_manager), + request_context_(request_context), + weak_ptr_factory_(this) {} + +SMSService::~SMSService() {} + +SMSService::Request* SMSService::CreateRequest( + const GURL& url, + const CompletionCallback& callback) { + return new RequestImpl(token_service_, signin_manager_, request_context_, url, + callback); +} + +void SMSService::QueryPhoneNumber(const PhoneNumberCallback& callback) { + CompletionCallback completion_callback = + base::Bind(&SMSService::QueryPhoneNumberCompletionCallback, + weak_ptr_factory_.GetWeakPtr(), callback); + + GURL url(kDesktopIOSPromotionQueryPhoneNumber); + Request* request = CreateRequest(url, completion_callback); + // This placeholder is required by the API. + request->SetPostData("{}"); + pending_requests_[request] = base::WrapUnique(request); + request->Start(); +} + +void SMSService::SendSMS(const std::string& promo_id, + const SMSService::PhoneNumberCallback& callback) { + CompletionCallback completion_callback = base::Bind( + &SMSService::SendSMSCallback, weak_ptr_factory_.GetWeakPtr(), callback); + GURL url(kDesktopIOSPromotionSendSMS); + Request* request = CreateRequest(url, completion_callback); + request->SetPostData( + base::StringPrintf(kSendSMSPromoFormat, promo_id.c_str())); + pending_requests_[request] = base::WrapUnique(request); + request->Start(); +} + +void SMSService::QueryPhoneNumberCompletionCallback( + const SMSService::PhoneNumberCallback& callback, + SMSService::Request* request, + bool success) { + std::unique_ptr<Request> request_ptr = std::move(pending_requests_[request]); + pending_requests_.erase(request); + + std::string phone_number; + bool has_number = false; + std::unique_ptr<base::Value> value = + base::JSONReader::Read(request->GetResponseBody()); + if (value.get() && value.get()->IsType(base::Value::Type::DICTIONARY)) { + const base::DictionaryValue* dictionary; + if (value->GetAsDictionary(&dictionary)) { + const base::ListValue* number_list; + if (dictionary->GetList("phoneNumber", &number_list)) { + const base::DictionaryValue* sub_dictionary; + // For now only handle the first number. + if (number_list->GetSize() > 0 && + number_list->GetDictionary(0, &sub_dictionary)) { + if (sub_dictionary->GetString("phoneNumber", &phone_number)) + has_number = true; + } + } + } + } + callback.Run(request, success && has_number, phone_number); +} + +void SMSService::SendSMSCallback( + const SMSService::PhoneNumberCallback& callback, + SMSService::Request* request, + bool success) { + std::unique_ptr<Request> request_ptr = std::move(pending_requests_[request]); + pending_requests_.erase(request); + + std::string phone_number; + bool has_number = false; + std::unique_ptr<base::Value> value = + base::JSONReader::Read(request->GetResponseBody()); + if (value.get() && value.get()->IsType(base::Value::Type::DICTIONARY)) { + const base::DictionaryValue* dictionary; + if (value->GetAsDictionary(&dictionary)) { + if (dictionary->GetString("phoneNumber", &phone_number)) + has_number = true; + } + } + callback.Run(request, success && has_number, phone_number); +}
diff --git a/chrome/browser/ui/desktop_ios_promotion/sms_service.h b/chrome/browser/ui/desktop_ios_promotion/sms_service.h new file mode 100644 index 0000000..6fb7e09 --- /dev/null +++ b/chrome/browser/ui/desktop_ios_promotion/sms_service.h
@@ -0,0 +1,109 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_DESKTOP_IOS_PROMOTION_SMS_SERVICE_H_ +#define CHROME_BROWSER_UI_DESKTOP_IOS_PROMOTION_SMS_SERVICE_H_ + +#include <stddef.h> + +#include <map> +#include <memory> +#include <string> +#include <vector> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "components/keyed_service/core/keyed_service.h" +#include "url/gurl.h" + +namespace net { +class URLRequestContextGetter; +} + +class OAuth2TokenService; +class SigninManagerBase; + +// Provides an API for querying a logged in users's verified phone number, +// and sending a predetermined promotional SMS to that number. This class is +// based heavily on WebHistoryService's implementation to query Google services. +class SMSService : public KeyedService { + public: + class Request { + public: + virtual ~Request(); + + virtual bool IsPending() = 0; + + // Returns the response code received from the server, which will only be + // valid if the request succeeded. + virtual int GetResponseCode() = 0; + + // Returns the contents of the response body received from the server. + virtual const std::string& GetResponseBody() = 0; + + virtual void SetPostData(const std::string& post_data) = 0; + + virtual void SetPostDataAndType(const std::string& post_data, + const std::string& mime_type) = 0; + + // Tells the request to begin. + virtual void Start() = 0; + + protected: + Request(); + }; + + typedef base::Callback< + void(Request*, bool success, const std::string& number)> + PhoneNumberCallback; + typedef base::Callback<void(Request*, bool success)> CompletionCallback; + + SMSService( + OAuth2TokenService* token_service, + SigninManagerBase* signin_manager, + const scoped_refptr<net::URLRequestContextGetter>& request_context); + ~SMSService() override; + + // Query the logged in user's verified phone number. + void QueryPhoneNumber(const PhoneNumberCallback& callback); + + // Send an SMS to the logged in user's verified phone number. The text of + // the SMS is determined by |promo_id|. + void SendSMS(const std::string& promo_id, + const SMSService::PhoneNumberCallback& callback); + + protected: + void QueryPhoneNumberCompletionCallback( + const SMSService::PhoneNumberCallback& callback, + SMSService::Request* request, + bool success); + + void SendSMSCallback(const SMSService::PhoneNumberCallback& callback, + SMSService::Request* request, + bool success); + + private: + virtual Request* CreateRequest(const GURL& url, + const CompletionCallback& callback); + + // Stores pointer to OAuth2TokenService and SigninManagerBase instance. They + // must outlive the SMSService and can be null during + // tests. + OAuth2TokenService* token_service_; + SigninManagerBase* signin_manager_; + + // Request context getter to use. + scoped_refptr<net::URLRequestContextGetter> request_context_; + + // Pending expiration requests to be canceled if not complete by profile + // shutdown. + std::map<Request*, std::unique_ptr<Request>> pending_requests_; + + base::WeakPtrFactory<SMSService> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(SMSService); +}; + +#endif // CHROME_BROWSER_UI_DESKTOP_IOS_PROMOTION_SMS_SERVICE_H_
diff --git a/chrome/browser/ui/desktop_ios_promotion/sms_service_factory.cc b/chrome/browser/ui/desktop_ios_promotion/sms_service_factory.cc new file mode 100644 index 0000000..536c117e --- /dev/null +++ b/chrome/browser/ui/desktop_ios_promotion/sms_service_factory.cc
@@ -0,0 +1,45 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/desktop_ios_promotion/sms_service_factory.h" + +#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" +#include "chrome/browser/signin/signin_manager_factory.h" +#include "chrome/browser/sync/profile_sync_service_factory.h" +#include "chrome/browser/ui/desktop_ios_promotion/sms_service.h" +#include "components/browser_sync/profile_sync_service.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "components/signin/core/browser/profile_oauth2_token_service.h" +#include "components/signin/core/browser/signin_manager.h" +#include "net/url_request/url_request_context_getter.h" + +// static +SMSServiceFactory* SMSServiceFactory::GetInstance() { + return base::Singleton<SMSServiceFactory>::get(); +} + +// static +SMSService* SMSServiceFactory::GetForProfile(Profile* profile) { + return static_cast<SMSService*>( + GetInstance()->GetServiceForBrowserContext(profile, true)); +} + +KeyedService* SMSServiceFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + Profile* profile = Profile::FromBrowserContext(context); + return new SMSService( + ProfileOAuth2TokenServiceFactory::GetForProfile(profile), + SigninManagerFactory::GetForProfile(profile), + profile->GetRequestContext()); +} + +SMSServiceFactory::SMSServiceFactory() + : BrowserContextKeyedServiceFactory( + "SMSServiceFactory", + BrowserContextDependencyManager::GetInstance()) { + DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance()); + DependsOn(SigninManagerFactory::GetInstance()); +} + +SMSServiceFactory::~SMSServiceFactory() {}
diff --git a/chrome/browser/ui/desktop_ios_promotion/sms_service_factory.h b/chrome/browser/ui/desktop_ios_promotion/sms_service_factory.h new file mode 100644 index 0000000..8d7b1f7e --- /dev/null +++ b/chrome/browser/ui/desktop_ios_promotion/sms_service_factory.h
@@ -0,0 +1,37 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_DESKTOP_IOS_PROMOTION_SMS_SERVICE_FACTORY_H_ +#define CHROME_BROWSER_UI_DESKTOP_IOS_PROMOTION_SMS_SERVICE_FACTORY_H_ + +#include "base/macros.h" +#include "base/memory/singleton.h" +#include "chrome/browser/profiles/profile.h" +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" + +class SMSService; + +class SMSServiceFactory : public BrowserContextKeyedServiceFactory { + public: + // Get the singleton instance of the factory. + static SMSServiceFactory* GetInstance(); + + // Get the SMSService for |profile|, creating one if needed. + static SMSService* GetForProfile(Profile* profile); + + protected: + // Overridden from BrowserContextKeyedServiceFactory. + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* context) const override; + + private: + friend struct base::DefaultSingletonTraits<SMSServiceFactory>; + + SMSServiceFactory(); + ~SMSServiceFactory() override; + + DISALLOW_COPY_AND_ASSIGN(SMSServiceFactory); +}; + +#endif // CHROME_BROWSER_UI_DESKTOP_IOS_PROMOTION_SMS_SERVICE_FACTORY_H_
diff --git a/chrome/browser/ui/desktop_ios_promotion/sms_service_unittest.cc b/chrome/browser/ui/desktop_ios_promotion/sms_service_unittest.cc new file mode 100644 index 0000000..ffe3a88 --- /dev/null +++ b/chrome/browser/ui/desktop_ios_promotion/sms_service_unittest.cc
@@ -0,0 +1,199 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/desktop_ios_promotion/sms_service.h" + +#include "base/run_loop.h" +#include "components/signin/core/browser/account_tracker_service.h" +#include "components/signin/core/browser/fake_profile_oauth2_token_service.h" +#include "components/signin/core/browser/fake_signin_manager.h" +#include "components/signin/core/browser/test_signin_client.h" +#include "net/http/http_status_code.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +// A testing web history service that does extra checks and creates a +// TestRequest instead of a normal request. +class TestingSMSService : public SMSService { + public: + explicit TestingSMSService( + ProfileOAuth2TokenService* token_service, + SigninManagerBase* signin_manager, + const scoped_refptr<net::URLRequestContextGetter>& request_context) + : SMSService(token_service, signin_manager, request_context) {} + + ~TestingSMSService() override {} + + SMSService::Request* CreateRequest( + const GURL& url, + const CompletionCallback& callback) override; + + void SetNextRequestResponseData(int response_code, + const std::string& response_body) { + next_response_code_ = response_code; + next_response_body_ = response_body; + } + + void QueryPhoneNumberCallbackSucceeded(SMSService::Request* request, + bool success, + const std::string& number) { + EXPECT_TRUE(success); + EXPECT_EQ(number, "1"); + } + + void QueryPhoneNumberCallbackFailed(SMSService::Request* request, + bool success, + const std::string& number) { + EXPECT_FALSE(success); + EXPECT_EQ(number, ""); + } + + private: + int next_response_code_; + std::string next_response_body_; + + DISALLOW_COPY_AND_ASSIGN(TestingSMSService); +}; + +// A testing request class that allows expected values to be filled in. +class TestRequest : public SMSService::Request { + public: + TestRequest(const SMSService::CompletionCallback& callback, + int response_code, + const std::string& response_body) + : callback_(callback), + response_code_(response_code), + response_body_(response_body), + is_pending_(false) {} + + ~TestRequest() override {} + + // history::Request overrides + bool IsPending() override { return is_pending_; } + int GetResponseCode() override { return response_code_; } + const std::string& GetResponseBody() override { return response_body_; } + void SetPostData(const std::string& post_data) override { + post_data_ = post_data; + } + void SetPostDataAndType(const std::string& post_data, + const std::string& mime_type) override { + SetPostData(post_data); + } + void Start() override { + is_pending_ = true; + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&TestRequest::MimicReturnFromFetch, base::Unretained(this))); + } + + void MimicReturnFromFetch() { + callback_.Run(this, response_code_ == net::HTTP_OK); + } + + private: + GURL url_; + SMSService::CompletionCallback callback_; + int response_code_; + std::string response_body_; + std::string post_data_; + bool is_pending_; + + DISALLOW_COPY_AND_ASSIGN(TestRequest); +}; + +SMSService::Request* TestingSMSService::CreateRequest( + const GURL& url, + const CompletionCallback& callback) { + SMSService::Request* request = + new TestRequest(callback, next_response_code_, next_response_body_); + return request; +} + +} // namespace + +// A test class used for testing the SMSService class. +// In order for SMSService to be valid, we must have a valid +// ProfileSyncService. Using the ProfileSyncServiceMock class allows to +// assign specific return values as needed to make sure the web history +// service is available. +class SMSServiceTest : public testing::Test { + public: + SMSServiceTest() + : signin_client_(nullptr), + signin_manager_(&signin_client_, &account_tracker_), + url_request_context_(new net::TestURLRequestContextGetter( + base::ThreadTaskRunnerHandle::Get())), + sms_service_(&token_service_, &signin_manager_, url_request_context_) {} + + ~SMSServiceTest() override {} + + void TearDown() override { + base::RunLoop run_loop; + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + run_loop.QuitClosure()); + run_loop.Run(); + } + + TestingSMSService* sms_service() { return &sms_service_; } + + void SetNextRequestResponseData(int response_code, + const std::string& response_body) { + sms_service_.SetNextRequestResponseData(response_code, response_body); + } + + private: + base::MessageLoop message_loop_; + FakeProfileOAuth2TokenService token_service_; + AccountTrackerService account_tracker_; + TestSigninClient signin_client_; + FakeSigninManagerBase signin_manager_; + scoped_refptr<net::URLRequestContextGetter> url_request_context_; + TestingSMSService sms_service_; + + DISALLOW_COPY_AND_ASSIGN(SMSServiceTest); +}; + +TEST_F(SMSServiceTest, VerifyJsonData) { + // Test that properly formatted response with good response code returns true + // as expected. + std::string query_phone_valid = + "{\n\"phoneNumber\": " + " [\n" + " {\"phoneNumber\": \"1\"}," + " {\"phoneNumber\": \"2\"}" + " ]\n" + "}"; + sms_service()->SetNextRequestResponseData(net::HTTP_OK, query_phone_valid); + sms_service()->QueryPhoneNumber( + base::Bind(&TestingSMSService::QueryPhoneNumberCallbackSucceeded, + base::Unretained(sms_service()))); + base::RunLoop().RunUntilIdle(); + std::string send_sms_valid = "{\"phoneNumber\": \"1\"}"; + sms_service()->SetNextRequestResponseData(net::HTTP_OK, send_sms_valid); + std::string promo_id = ""; + sms_service()->SendSMS( + promo_id, + base::Bind(&TestingSMSService::QueryPhoneNumberCallbackSucceeded, + base::Unretained(sms_service()))); + base::RunLoop().RunUntilIdle(); + // Test that improperly formatted response returns no number. + std::string query_phone_invalid = + "{\n\"phoneNumber\": " + " [\n" + " ]\n" + "}"; + sms_service()->SetNextRequestResponseData(net::HTTP_OK, query_phone_invalid); + sms_service()->QueryPhoneNumber( + base::Bind(&TestingSMSService::QueryPhoneNumberCallbackFailed, + base::Unretained(sms_service()))); + base::RunLoop().RunUntilIdle(); + std::string send_sms_invalid = "{}"; + sms_service()->SetNextRequestResponseData(net::HTTP_OK, send_sms_invalid); + sms_service()->SendSMS( + promo_id, base::Bind(&TestingSMSService::QueryPhoneNumberCallbackFailed, + base::Unretained(sms_service()))); + base::RunLoop().RunUntilIdle(); +}
diff --git a/chrome/browser/ui/views/media_router/media_router_ui_browsertest.cc b/chrome/browser/ui/views/media_router/media_router_ui_browsertest.cc index 9a372f34..63820ad 100644 --- a/chrome/browser/ui/views/media_router/media_router_ui_browsertest.cc +++ b/chrome/browser/ui/views/media_router/media_router_ui_browsertest.cc
@@ -124,8 +124,16 @@ MediaRouterActionController* action_controller_ = nullptr; }; +#if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_WIN) +// Flaky on chromeos, linux, win: https://crbug.com/658005 +#define MAYBE_OpenDialogWithMediaRouterAction \ + DISABLED_OpenDialogWithMediaRouterAction +#else +#define MAYBE_OpenDialogWithMediaRouterAction OpenDialogWithMediaRouterAction +#endif + IN_PROC_BROWSER_TEST_F(MediaRouterUIBrowserTest, - OpenDialogWithMediaRouterAction) { + MAYBE_OpenDialogWithMediaRouterAction) { // We start off at about:blank page. // Make sure there is 1 tab and media router is enabled. ASSERT_EQ(1, browser()->tab_strip_model()->count());
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 6f26ffd..b8359a4 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -126,6 +126,11 @@ // Enabled or disabled the Material Design version of chrome://extensions. const base::Feature kMaterialDesignExtensions{ "MaterialDesignExtensions", base::FEATURE_DISABLED_BY_DEFAULT}; + +// Sets whether dismissing the new-tab-page override bubble counts as +// acknowledgement. +extern const base::Feature kAcknowledgeNtpOverrideOnDeactivate{ + "AcknowledgeNtpOverrideOnDeactivate", base::FEATURE_DISABLED_BY_DEFAULT}; #endif // Enables or disables the Material Design version of chrome://history.
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index d78d6c7..14748db 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -78,6 +78,7 @@ #if BUILDFLAG(ENABLE_EXTENSIONS) extern const base::Feature kMaterialDesignExtensions; +extern const base::Feature kAcknowledgeNtpOverrideOnDeactivate; #endif extern const base::Feature kMaterialDesignHistory;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 59eddeb..b953ff92 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3766,6 +3766,7 @@ "../browser/ui/autofill/country_combobox_model_unittest.cc", "../browser/ui/autofill/save_card_bubble_controller_impl_unittest.cc", "../browser/ui/bluetooth/bluetooth_chooser_controller_unittest.cc", + "../browser/ui/desktop_ios_promotion/sms_service_unittest.cc", "../browser/ui/passwords/manage_passwords_ui_controller_unittest.cc", ] deps += [
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 3f2e6e657..d43dc48f 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -9236.0.0 \ No newline at end of file +9240.0.0 \ No newline at end of file
diff --git a/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java b/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java index 0a0d77a..73a688b 100644 --- a/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java +++ b/components/cronet/android/java/src/org/chromium/net/urlconnection/CronetHttpURLConnection.java
@@ -45,8 +45,9 @@ private CronetOutputStream mOutputStream; private UrlResponseInfo mResponseInfo; private CronetException mException; - private boolean mOnRedirectCalled = false; - private boolean mHasResponse = false; + private boolean mOnRedirectCalled; + // Whether response headers are received, the request is failed, or the request is canceled. + private boolean mHasResponseHeadersOrCompleted; private List<Map.Entry<String, String>> mResponseHeadersList; private Map<String, List<String>> mResponseHeadersMap; @@ -437,6 +438,7 @@ @Override public void onResponseStarted(UrlRequest request, UrlResponseInfo info) { mResponseInfo = info; + mHasResponseHeadersOrCompleted = true; // Quits the message loop since we have the headers now. mMessageLoop.quit(); } @@ -508,7 +510,7 @@ if (mOutputStream != null) { mOutputStream.setRequestCompleted(exception); } - mHasResponse = true; + mHasResponseHeadersOrCompleted = true; mMessageLoop.quit(); } } @@ -525,13 +527,12 @@ mOutputStream.close(); } } - if (!mHasResponse) { + if (!mHasResponseHeadersOrCompleted) { startRequest(); // Blocks until onResponseStarted or onFailed is called. mMessageLoop.loop(); - mHasResponse = true; } - checkHasResponse(); + checkHasResponseHeaders(); } /** @@ -539,8 +540,8 @@ * an exception occurred before headers received. This method should only be * called after onResponseStarted or onFailed. */ - private void checkHasResponse() throws IOException { - if (!mHasResponse) throw new IllegalStateException("No response."); + private void checkHasResponseHeaders() throws IOException { + if (!mHasResponseHeadersOrCompleted) throw new IllegalStateException("No response."); if (mException != null) { throw mException; } else if (mResponseInfo == null) {
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/urlconnection/CronetFixedModeOutputStreamTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/urlconnection/CronetFixedModeOutputStreamTest.java index ea4e624..87cdd62 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/urlconnection/CronetFixedModeOutputStreamTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/urlconnection/CronetFixedModeOutputStreamTest.java
@@ -68,6 +68,23 @@ @SmallTest @Feature({"Cronet"}) @CompareDefaultWithCronet + // Regression test for crbug.com/687600. + public void testZeroLengthWriteWithNoResponseBody() throws Exception { + URL url = new URL(NativeTestServer.getEchoBodyURL()); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setDoOutput(true); + connection.setRequestMethod("POST"); + connection.setFixedLengthStreamingMode(0); + OutputStream out = connection.getOutputStream(); + out.write(new byte[] {}); + assertEquals(200, connection.getResponseCode()); + assertEquals("OK", connection.getResponseMessage()); + connection.disconnect(); + } + + @SmallTest + @Feature({"Cronet"}) + @CompareDefaultWithCronet public void testWriteAfterRequestFailed() throws Exception { URL url = new URL(NativeTestServer.getEchoBodyURL()); HttpURLConnection connection = (HttpURLConnection) url.openConnection();
diff --git a/components/dom_distiller/core/dom_distiller_service.cc b/components/dom_distiller/core/dom_distiller_service.cc index 78534bf..bb31c6a0 100644 --- a/components/dom_distiller/core/dom_distiller_service.cc +++ b/components/dom_distiller/core/dom_distiller_service.cc
@@ -55,6 +55,9 @@ } syncer::SyncableService* DomDistillerService::GetSyncableService() const { + if (!store_) { + return nullptr; + } return store_->GetSyncableService(); } @@ -75,7 +78,7 @@ std::unique_ptr<DistillerPage> distiller_page, const ArticleAvailableCallback& article_cb) { ArticleEntry entry; - const bool is_already_added = store_->GetEntryByUrl(url, &entry); + const bool is_already_added = store_ && store_->GetEntryByUrl(url, &entry); TaskTracker* task_tracker = nullptr; if (is_already_added) { @@ -112,18 +115,21 @@ } bool DomDistillerService::HasEntry(const std::string& entry_id) { - return store_->GetEntryById(entry_id, NULL); + return store_ && store_->GetEntryById(entry_id, NULL); } std::string DomDistillerService::GetUrlForEntry(const std::string& entry_id) { ArticleEntry entry; - if (store_->GetEntryById(entry_id, &entry)) { + if (store_ && store_->GetEntryById(entry_id, &entry)) { return entry.pages().Get(0).url(); } return ""; } std::vector<ArticleEntry> DomDistillerService::GetEntries() const { + if (!store_) { + return std::vector<ArticleEntry>(); + } return store_->GetEntries(); } @@ -136,7 +142,7 @@ task_tracker->CancelSaveCallbacks(); } - if (!store_->GetEntryById(entry_id, entry.get())) { + if (!store_ || !store_->GetEntryById(entry_id, entry.get())) { return std::unique_ptr<ArticleEntry>(); } @@ -151,7 +157,7 @@ std::unique_ptr<DistillerPage> distiller_page, const std::string& entry_id) { ArticleEntry entry; - if (!store_->GetEntryById(entry_id, &entry)) { + if (!store_ || !store_->GetEntryById(entry_id, &entry)) { return std::unique_ptr<ViewerHandle>(); } @@ -194,7 +200,7 @@ const GURL& url, TaskTracker** task_tracker) { ArticleEntry entry; - if (store_->GetEntryByUrl(url, &entry)) { + if (store_ && store_->GetEntryByUrl(url, &entry)) { return GetOrCreateTaskTrackerForEntry(entry, task_tracker); } @@ -261,7 +267,7 @@ const DistilledArticleProto* article_proto, bool distillation_succeeded) { DCHECK(IsEntryValid(entry)); - if (distillation_succeeded) { + if (store_ && distillation_succeeded) { DCHECK(article_proto); DCHECK_GT(article_proto->pages_size(), 0); store_->AddEntry(entry); @@ -271,12 +277,16 @@ void DomDistillerService::AddObserver(DomDistillerObserver* observer) { DCHECK(observer); - store_->AddObserver(observer); + if (store_) { + store_->AddObserver(observer); + } } void DomDistillerService::RemoveObserver(DomDistillerObserver* observer) { DCHECK(observer); - store_->RemoveObserver(observer); + if (store_) { + store_->RemoveObserver(observer); + } } DistilledPagePrefs* DomDistillerService::GetDistilledPagePrefs() {
diff --git a/components/exo/pointer.cc b/components/exo/pointer.cc index 9ca231e5..31b4299 100644 --- a/components/exo/pointer.cc +++ b/components/exo/pointer.cc
@@ -74,6 +74,9 @@ if (!focus_) return; + // This is used to avoid unnecessary cursor changes. + bool cursor_changed = false; + // If surface is different than the current pointer surface then remove the // current surface and add the new surface. if (surface != surface_) { @@ -100,10 +103,18 @@ ->GetContainer(ash::kShellWindowId_MouseCursorContainer) ->AddChild(surface_->window()); } + cursor_changed = true; } // Update hotspot. - hotspot_ = hotspot; + if (hotspot != hotspot_) { + hotspot_ = hotspot; + cursor_changed = true; + } + + // Early out if cursor did not change. + if (!cursor_changed) + return; // If |surface_| is set then ascynchrounsly capture a snapshot of cursor, // otherwise cancel pending capture and immediately set the cursor to "none". @@ -225,7 +236,7 @@ void Pointer::OnCursorSetChanged(ui::CursorSetType cursor_set) { // Capture new cursor in case UI scale changed. if (focus_ && surface_) - UpdateCursor(); + CaptureCursor(); } ////////////////////////////////////////////////////////////////////////////////
diff --git a/components/guest_view/renderer/guest_view_container.cc b/components/guest_view/renderer/guest_view_container.cc index 4d5c341..890fb36 100644 --- a/components/guest_view/renderer/guest_view_container.cc +++ b/components/guest_view/renderer/guest_view_container.cc
@@ -4,6 +4,7 @@ #include "components/guest_view/renderer/guest_view_container.h" +#include "base/lazy_instance.h" #include "base/macros.h" #include "base/threading/thread_task_runner_handle.h" #include "components/guest_view/common/guest_view_constants.h"
diff --git a/components/nacl/browser/PRESUBMIT.py b/components/nacl/browser/PRESUBMIT.py new file mode 100644 index 0000000..b2cac48 --- /dev/null +++ b/components/nacl/browser/PRESUBMIT.py
@@ -0,0 +1,27 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Chromium presubmit script to check that BadMessage enums in histograms.xml +match the corresponding bad_message.h file. +""" + +def _RunHistogramChecks(input_api, output_api, histogram_name): + try: + # Setup sys.path so that we can call histrogram code + import sys + original_sys_path = sys.path + sys.path = sys.path + [input_api.os_path.join( + input_api.change.RepositoryRoot(), + 'tools', 'metrics', 'histograms')] + + import presubmit_bad_message_reasons + return presubmit_bad_message_reasons.PrecheckBadMessage(input_api, + output_api, histogram_name) + except: + return [output_api.PresubmitError('Could not verify histogram!')] + finally: + sys.path = original_sys_path + +def CheckChangeOnUpload(input_api, output_api): + return _RunHistogramChecks(input_api, output_api, "BadMessageReasonNaCl")
diff --git a/components/ntp_snippets/bookmarks/bookmark_suggestions_provider.cc b/components/ntp_snippets/bookmarks/bookmark_suggestions_provider.cc index 0b452a0e..8a6e5b8 100644 --- a/components/ntp_snippets/bookmarks/bookmark_suggestions_provider.cc +++ b/components/ntp_snippets/bookmarks/bookmark_suggestions_provider.cc
@@ -110,8 +110,7 @@ return CategoryInfo( l10n_util::GetStringUTF16(IDS_NTP_BOOKMARK_SUGGESTIONS_SECTION_HEADER), ContentSuggestionsCardLayout::MINIMAL_CARD, - /*has_more_action=*/false, - /*has_reload_action=*/false, + /*has_fetch_action=*/false, /*has_view_all_action=*/true, /*show_if_empty=*/false, l10n_util::GetStringUTF16(IDS_NTP_BOOKMARK_SUGGESTIONS_SECTION_EMPTY));
diff --git a/components/ntp_snippets/category_info.cc b/components/ntp_snippets/category_info.cc index e3d3058d..e8b32ea 100644 --- a/components/ntp_snippets/category_info.cc +++ b/components/ntp_snippets/category_info.cc
@@ -8,15 +8,13 @@ CategoryInfo::CategoryInfo(const base::string16& title, ContentSuggestionsCardLayout card_layout, - bool has_more_action, - bool has_reload_action, + bool has_fetch_action, bool has_view_all_action, bool show_if_empty, const base::string16& no_suggestions_message) : title_(title), card_layout_(card_layout), - has_more_action_(has_more_action), - has_reload_action_(has_reload_action), + has_fetch_action_(has_fetch_action), has_view_all_action_(has_view_all_action), show_if_empty_(show_if_empty), no_suggestions_message_(no_suggestions_message) {}
diff --git a/components/ntp_snippets/category_info.h b/components/ntp_snippets/category_info.h index dadf287..a85e867 100644 --- a/components/ntp_snippets/category_info.h +++ b/components/ntp_snippets/category_info.h
@@ -25,8 +25,7 @@ public: CategoryInfo(const base::string16& title, ContentSuggestionsCardLayout card_layout, - bool has_more_action, - bool has_reload_action, + bool has_fetch_action, bool has_view_all_action, bool show_if_empty, const base::string16& no_suggestions_message); @@ -43,13 +42,9 @@ // Layout of the cards to be used to display suggestions in this category. ContentSuggestionsCardLayout card_layout() const { return card_layout_; } - // Whether the category supports a "More" action, that triggers fetching more - // suggestions for the category, while keeping the current ones. - bool has_more_action() const { return has_more_action_; } - - // Whether the category supports a "Reload" action, that triggers fetching new - // suggestions to replace the current ones. - bool has_reload_action() const { return has_reload_action_; } + // Whether the category supports a "Fetch" action, that triggers fetching more + // suggestions for the category. + bool has_fetch_action() const { return has_fetch_action_; } // Whether the category supports a "ViewAll" action, that triggers displaying // all the content related to the current categories. @@ -70,8 +65,7 @@ ContentSuggestionsCardLayout card_layout_; // Supported actions for the category. - bool has_more_action_; - bool has_reload_action_; + bool has_fetch_action_; bool has_view_all_action_; // Whether to show the category if a fetch returns no suggestions.
diff --git a/components/ntp_snippets/content_suggestions_service_unittest.cc b/components/ntp_snippets/content_suggestions_service_unittest.cc index 29ddca3..0ada9202 100644 --- a/components/ntp_snippets/content_suggestions_service_unittest.cc +++ b/components/ntp_snippets/content_suggestions_service_unittest.cc
@@ -433,8 +433,7 @@ const CategoryInfo& actual = result.value(); EXPECT_THAT(expected.title(), Eq(actual.title())); EXPECT_THAT(expected.card_layout(), Eq(actual.card_layout())); - EXPECT_THAT(expected.has_more_action(), Eq(actual.has_more_action())); - EXPECT_THAT(expected.has_reload_action(), Eq(actual.has_reload_action())); + EXPECT_THAT(expected.has_fetch_action(), Eq(actual.has_fetch_action())); EXPECT_THAT(expected.has_view_all_action(), Eq(actual.has_view_all_action())); }
diff --git a/components/ntp_snippets/mock_content_suggestions_provider.cc b/components/ntp_snippets/mock_content_suggestions_provider.cc index 02c99b6..007ecb16 100644 --- a/components/ntp_snippets/mock_content_suggestions_provider.cc +++ b/components/ntp_snippets/mock_content_suggestions_provider.cc
@@ -37,8 +37,10 @@ CategoryInfo MockContentSuggestionsProvider::GetCategoryInfo( Category category) { return CategoryInfo(base::ASCIIToUTF16("Section title"), - ContentSuggestionsCardLayout::FULL_CARD, true, false, - true, false, + ContentSuggestionsCardLayout::FULL_CARD, + /*has_fetch_action=*/true, + /*has_view_all_action=*/true, + /*show_if_empty=*/false, base::ASCIIToUTF16("No suggestions message")); }
diff --git a/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.cc b/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.cc index f8056d0f..7ef2d6e 100644 --- a/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.cc +++ b/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider.cc
@@ -111,8 +111,7 @@ return CategoryInfo( l10n_util::GetStringUTF16(IDS_NTP_RECENT_TAB_SUGGESTIONS_SECTION_HEADER), ContentSuggestionsCardLayout::MINIMAL_CARD, - /*has_more_action=*/false, - /*has_reload_action=*/false, + /*has_fetch_action=*/false, /*has_view_all_action=*/false, /*show_if_empty=*/false, l10n_util::GetStringUTF16(IDS_NTP_RECENT_TAB_SUGGESTIONS_SECTION_EMPTY));
diff --git a/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider_unittest.cc b/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider_unittest.cc index 64acc93..bc3d6d2 100644 --- a/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider_unittest.cc +++ b/components/ntp_snippets/offline_pages/recent_tab_suggestions_provider_unittest.cc
@@ -177,9 +177,7 @@ TEST_F(RecentTabSuggestionsProviderTest, ShouldDeliverCorrectCategoryInfo) { EXPECT_FALSE( - provider()->GetCategoryInfo(recent_tabs_category()).has_more_action()); - EXPECT_FALSE( - provider()->GetCategoryInfo(recent_tabs_category()).has_reload_action()); + provider()->GetCategoryInfo(recent_tabs_category()).has_fetch_action()); EXPECT_FALSE(provider() ->GetCategoryInfo(recent_tabs_category()) .has_view_all_action());
diff --git a/components/ntp_snippets/physical_web_pages/physical_web_page_suggestions_provider.cc b/components/ntp_snippets/physical_web_pages/physical_web_page_suggestions_provider.cc index 27cfb98..7e73cdd 100644 --- a/components/ntp_snippets/physical_web_pages/physical_web_page_suggestions_provider.cc +++ b/components/ntp_snippets/physical_web_pages/physical_web_page_suggestions_provider.cc
@@ -117,8 +117,7 @@ return CategoryInfo(l10n_util::GetStringUTF16( IDS_NTP_PHYSICAL_WEB_PAGE_SUGGESTIONS_SECTION_HEADER), ContentSuggestionsCardLayout::FULL_CARD, - /*has_more_action=*/false, - /*has_reload_action=*/false, + /*has_fetch_action=*/false, /*has_view_all_action=*/false, /*show_if_empty=*/false, l10n_util::GetStringUTF16(
diff --git a/components/ntp_snippets/remote/json_request.cc b/components/ntp_snippets/remote/json_request.cc index 8e522936..ec52caa 100644 --- a/components/ntp_snippets/remote/json_request.cc +++ b/components/ntp_snippets/remote/json_request.cc
@@ -139,10 +139,7 @@ : l10n_util::GetStringUTF16( IDS_NTP_ARTICLE_SUGGESTIONS_SECTION_HEADER), ContentSuggestionsCardLayout::FULL_CARD, - // TODO(dgn): merge has_more_action and has_reload_action when we remove - // the kFetchMoreFeature flag. See https://crbug.com/667752 - /*has_more_action=*/true, - /*has_reload_action=*/true, + /*has_fetch_action=*/true, /*has_view_all_action=*/false, /*show_if_empty=*/true, l10n_util::GetStringUTF16(IDS_NTP_ARTICLE_SUGGESTIONS_SECTION_EMPTY)); @@ -152,10 +149,7 @@ bool allow_fetching_more_results) { return CategoryInfo( title, ContentSuggestionsCardLayout::FULL_CARD, - // TODO(dgn): merge has_more_action and has_reload_action when we remove - // the kFetchMoreFeature flag. See https://crbug.com/667752 - /*has_more_action=*/allow_fetching_more_results, - /*has_reload_action=*/allow_fetching_more_results, + /*has_fetch_action=*/allow_fetching_more_results, /*has_view_all_action=*/false, /*show_if_empty=*/false, // TODO(tschumann): The message for no-articles is likely wrong
diff --git a/components/ntp_snippets/remote/remote_suggestions_fetcher.cc b/components/ntp_snippets/remote/remote_suggestions_fetcher.cc index 56eaa12..80fa8c3 100644 --- a/components/ntp_snippets/remote/remote_suggestions_fetcher.cc +++ b/components/ntp_snippets/remote/remote_suggestions_fetcher.cc
@@ -211,10 +211,7 @@ : l10n_util::GetStringUTF16( IDS_NTP_ARTICLE_SUGGESTIONS_SECTION_HEADER), ContentSuggestionsCardLayout::FULL_CARD, - // TODO(dgn): merge has_more_action and has_reload_action when we remove - // the kFetchMoreFeature flag. See https://crbug.com/667752 - /*has_more_action=*/true, - /*has_reload_action=*/true, + /*has_fetch_action=*/true, /*has_view_all_action=*/false, /*show_if_empty=*/true, l10n_util::GetStringUTF16(IDS_NTP_ARTICLE_SUGGESTIONS_SECTION_EMPTY)); @@ -224,10 +221,7 @@ bool allow_fetching_more_results) { return CategoryInfo( title, ContentSuggestionsCardLayout::FULL_CARD, - // TODO(dgn): merge has_more_action and has_reload_action when we remove - // the kFetchMoreFeature flag. See https://crbug.com/667752 - /*has_more_action=*/allow_fetching_more_results, - /*has_reload_action=*/allow_fetching_more_results, + /*has_fetch_action=*/allow_fetching_more_results, /*has_view_all_action=*/false, /*show_if_empty=*/false, // TODO(tschumann): The message for no-articles is likely wrong
diff --git a/components/ntp_snippets/remote/remote_suggestions_fetcher_unittest.cc b/components/ntp_snippets/remote/remote_suggestions_fetcher_unittest.cc index 86b4bb1..14ac6b1 100644 --- a/components/ntp_snippets/remote/remote_suggestions_fetcher_unittest.cc +++ b/components/ntp_snippets/remote/remote_suggestions_fetcher_unittest.cc
@@ -115,12 +115,8 @@ } MATCHER(IsCategoryInfoForArticles, "") { - if (!arg.has_more_action()) { - *result_listener << "missing expected has_more_action"; - return false; - } - if (!arg.has_reload_action()) { - *result_listener << "missing expected has_reload_action"; + if (!arg.has_fetch_action()) { + *result_listener << "missing expected has_fetc_action"; return false; } if (arg.has_view_all_action()) { @@ -558,8 +554,7 @@ } else if (category.category == Category::FromRemoteCategory(2)) { ASSERT_THAT(articles.size(), Eq(1u)); EXPECT_THAT(articles[0]->url().spec(), Eq("http://localhost/foo2")); - EXPECT_THAT(category.info.has_more_action(), Eq(true)); - EXPECT_THAT(category.info.has_reload_action(), Eq(true)); + EXPECT_THAT(category.info.has_fetch_action(), Eq(true)); EXPECT_THAT(category.info.has_view_all_action(), Eq(false)); EXPECT_THAT(category.info.show_if_empty(), Eq(false)); } else { @@ -611,7 +606,7 @@ ASSERT_TRUE(fetched_categories); ASSERT_THAT(fetched_categories->size(), Eq(1u)); - EXPECT_THAT(fetched_categories->front().info.has_more_action(), Eq(false)); + EXPECT_THAT(fetched_categories->front().info.has_fetch_action(), Eq(false)); EXPECT_THAT(fetched_categories->front().info.title(), Eq(base::UTF8ToUTF16("Articles for Me"))); }
diff --git a/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc b/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc index 719a46b..1459386 100644 --- a/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc +++ b/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc
@@ -1256,7 +1256,7 @@ dict->SetBoolean(kCategoryContentProvidedByServer, content.included_in_last_server_response); dict->SetBoolean(kCategoryContentAllowFetchingMore, - content.info.has_more_action()); + content.info.has_fetch_action()); list.Append(std::move(dict)); } // Finally, store the result in the pref service.
diff --git a/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc b/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc index 32c7a68..84b83172 100644 --- a/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc +++ b/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc
@@ -588,8 +588,7 @@ CategoryInfo info_before = service->GetCategoryInfo(articles_category()); ASSERT_THAT(info_before.title(), Not(IsEmpty())); ASSERT_THAT(info_before.title(), Not(Eq(test_default_title))); - EXPECT_THAT(info_before.has_more_action(), Eq(true)); - EXPECT_THAT(info_before.has_reload_action(), Eq(true)); + EXPECT_THAT(info_before.has_fetch_action(), Eq(true)); EXPECT_THAT(info_before.has_view_all_action(), Eq(false)); EXPECT_THAT(info_before.show_if_empty(), Eq(true)); @@ -606,8 +605,7 @@ CategoryInfo info_with_title = service->GetCategoryInfo(articles_category()); EXPECT_THAT(info_before.title(), Not(Eq(info_with_title.title()))); EXPECT_THAT(test_default_title, Eq(info_with_title.title())); - EXPECT_THAT(info_before.has_more_action(), Eq(true)); - EXPECT_THAT(info_before.has_reload_action(), Eq(true)); + EXPECT_THAT(info_before.has_fetch_action(), Eq(true)); EXPECT_THAT(info_before.has_view_all_action(), Eq(false)); EXPECT_THAT(info_before.show_if_empty(), Eq(true)); } @@ -663,8 +661,7 @@ TEST_F(RemoteSuggestionsProviderImplTest, ArticleCategoryInfo) { auto service = MakeSuggestionsProvider(); CategoryInfo article_info = service->GetCategoryInfo(articles_category()); - EXPECT_THAT(article_info.has_more_action(), Eq(true)); - EXPECT_THAT(article_info.has_reload_action(), Eq(true)); + EXPECT_THAT(article_info.has_fetch_action(), Eq(true)); EXPECT_THAT(article_info.has_view_all_action(), Eq(false)); EXPECT_THAT(article_info.show_if_empty(), Eq(true)); } @@ -681,8 +678,7 @@ LoadFromJSONString(service.get(), json_str); CategoryInfo info = service->GetCategoryInfo(unknown_category()); - EXPECT_THAT(info.has_more_action(), Eq(false)); - EXPECT_THAT(info.has_reload_action(), Eq(false)); + EXPECT_THAT(info.has_fetch_action(), Eq(false)); EXPECT_THAT(info.has_view_all_action(), Eq(false)); EXPECT_THAT(info.show_if_empty(), Eq(false)); }
diff --git a/components/ntp_snippets/sessions/foreign_sessions_suggestions_provider.cc b/components/ntp_snippets/sessions/foreign_sessions_suggestions_provider.cc index 0d05469f..0e13fb1 100644 --- a/components/ntp_snippets/sessions/foreign_sessions_suggestions_provider.cc +++ b/components/ntp_snippets/sessions/foreign_sessions_suggestions_provider.cc
@@ -199,8 +199,7 @@ return CategoryInfo(l10n_util::GetStringUTF16( IDS_NTP_FOREIGN_SESSIONS_SUGGESTIONS_SECTION_HEADER), ContentSuggestionsCardLayout::MINIMAL_CARD, - /*has_more_action=*/false, - /*has_reload_action=*/false, + /*has_fetch_action=*/false, /*has_view_all_action=*/true, /*show_if_empty=*/false, l10n_util::GetStringUTF16(
diff --git a/components/password_manager/content/browser/PRESUBMIT.py b/components/password_manager/content/browser/PRESUBMIT.py new file mode 100644 index 0000000..1507afc4 --- /dev/null +++ b/components/password_manager/content/browser/PRESUBMIT.py
@@ -0,0 +1,28 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Chromium presubmit script to check that BadMessage enums in histograms.xml +match the corresponding bad_message.h file. +""" + +def _RunHistogramChecks(input_api, output_api, histogram_name): + try: + # Setup sys.path so that we can call histrogram code + import sys + original_sys_path = sys.path + sys.path = sys.path + [input_api.os_path.join( + input_api.change.RepositoryRoot(), + 'tools', 'metrics', 'histograms')] + + import presubmit_bad_message_reasons + return presubmit_bad_message_reasons.PrecheckBadMessage(input_api, + output_api, histogram_name) + except: + return [output_api.PresubmitError('Could not verify histogram!')] + finally: + sys.path = original_sys_path + +def CheckChangeOnUpload(input_api, output_api): + return _RunHistogramChecks(input_api, output_api, + "BadMessageReasonPasswordManager")
diff --git a/content/browser/PRESUBMIT.py b/content/browser/PRESUBMIT.py new file mode 100644 index 0000000..67e1c2a7 --- /dev/null +++ b/content/browser/PRESUBMIT.py
@@ -0,0 +1,28 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Chromium presubmit script to check that BadMessage enums in histograms.xml +match the corresponding bad_message.h file. +""" + +def _RunHistogramChecks(input_api, output_api, histogram_name): + try: + # Setup sys.path so that we can call histrogram code + import sys + original_sys_path = sys.path + sys.path = sys.path + [input_api.os_path.join( + input_api.change.RepositoryRoot(), + 'tools', 'metrics', 'histograms')] + + import presubmit_bad_message_reasons + return presubmit_bad_message_reasons.PrecheckBadMessage(input_api, + output_api, histogram_name) + except Exception as e: + return [output_api.PresubmitError("Error verifying histogram (%s)." + % str(e))] + finally: + sys.path = original_sys_path + +def CheckChangeOnUpload(input_api, output_api): + return _RunHistogramChecks(input_api, output_api, "BadMessageReasonContent")
diff --git a/content/browser/bluetooth/bluetooth_metrics.cc b/content/browser/bluetooth/bluetooth_metrics.cc index 84421ee..d9ae54fb 100644 --- a/content/browser/bluetooth/bluetooth_metrics.cc +++ b/content/browser/bluetooth/bluetooth_metrics.cc
@@ -283,6 +283,9 @@ case UMAGATTOperation::DESCRIPTOR_READ: RecordDescriptorReadValueOutcome(outcome); return; + case UMAGATTOperation::DESCRIPTOR_WRITE: + RecordDescriptorWriteValueOutcome(outcome); + return; case UMAGATTOperation::COUNT: NOTREACHED(); return; @@ -368,6 +371,19 @@ TranslateCacheQueryOutcomeToGATTOperationOutcome(outcome)); } +// Descriptor.writeValue + +void RecordDescriptorWriteValueOutcome(UMAGATTOperationOutcome outcome) { + UMA_HISTOGRAM_ENUMERATION("Bluetooth.Web.Descriptor.WriteValue.Outcome", + static_cast<int>(outcome), + static_cast<int>(UMAGATTOperationOutcome::COUNT)); +} + +void RecordDescriptorWriteValueOutcome(CacheQueryOutcome outcome) { + RecordDescriptorWriteValueOutcome( + TranslateCacheQueryOutcomeToGATTOperationOutcome(outcome)); +} + void RecordRSSISignalStrengthLevel(UMARSSISignalStrengthLevel level) { UMA_HISTOGRAM_ENUMERATION( "Bluetooth.Web.RequestDevice.RSSISignalStrengthLevel",
diff --git a/content/browser/bluetooth/bluetooth_metrics.h b/content/browser/bluetooth/bluetooth_metrics.h index 65ad7b4..64c10887 100644 --- a/content/browser/bluetooth/bluetooth_metrics.h +++ b/content/browser/bluetooth/bluetooth_metrics.h
@@ -36,6 +36,7 @@ SERVICE_GET_CHARACTERISTICS = 9, GET_PRIMARY_SERVICES = 10, DESCRIPTOR_READ_VALUE = 11, + DESCRIPTOR_WRITE_VALUE = 12, // NOTE: Add new actions immediately above this line. Make sure to update // the enum list in tools/metrics/histograms/histograms.xml accordingly. COUNT @@ -239,6 +240,7 @@ CHARACTERISTIC_WRITE, START_NOTIFICATIONS, DESCRIPTOR_READ, + DESCRIPTOR_WRITE, // Note: Add new GATT Operations immediately above this line. COUNT }; @@ -289,6 +291,16 @@ // QueryCacheForDescriptor fails. void RecordDescriptorReadValueOutcome(CacheQueryOutcome outcome); +// Descriptor.writeValue() Metrics +// There should be a call to this function for every call to +// Send(BluetoothMsg_ReadDescriptorValueSuccess) and +// Send(BluetoothMsg_ReadDescriptorValueError). +void RecordDescriptorWriteValueOutcome(UMAGATTOperationOutcome error); + +// Records the outcome of a cache query for writeValue. Should only be called if +// QueryCacheForDescriptor fails. +void RecordDescriptorWriteValueOutcome(CacheQueryOutcome outcome); + enum class UMARSSISignalStrengthLevel { LESS_THAN_OR_EQUAL_TO_MIN_RSSI, LEVEL_0,
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.cc b/content/browser/bluetooth/web_bluetooth_service_impl.cc index 5adce0e..be6853b 100644 --- a/content/browser/bluetooth/web_bluetooth_service_impl.cc +++ b/content/browser/bluetooth/web_bluetooth_service_impl.cc
@@ -775,6 +775,49 @@ weak_ptr_factory_.GetWeakPtr(), callback)); } +void WebBluetoothServiceImpl::RemoteDescriptorWriteValue( + const std::string& descriptor_instance_id, + const std::vector<uint8_t>& value, + const RemoteDescriptorWriteValueCallback& callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + RecordWebBluetoothFunctionCall( + UMAWebBluetoothFunction::DESCRIPTOR_WRITE_VALUE); + + // We perform the length check on the renderer side. So if we + // get a value with length > 512, we can assume it's a hostile + // renderer and kill it. + if (value.size() > 512) { + CrashRendererAndClosePipe(bad_message::BDH_INVALID_WRITE_VALUE_LENGTH); + return; + } + + const CacheQueryResult query_result = + QueryCacheForDescriptor(descriptor_instance_id); + + if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) { + return; + } + + if (query_result.outcome != CacheQueryOutcome::SUCCESS) { + RecordDescriptorWriteValueOutcome(query_result.outcome); + callback.Run(query_result.GetWebResult()); + return; + } + + if (BluetoothBlocklist::Get().IsExcludedFromWrites( + query_result.descriptor->GetUUID())) { + RecordDescriptorWriteValueOutcome(UMAGATTOperationOutcome::BLOCKLISTED); + callback.Run(blink::mojom::WebBluetoothResult::BLOCKLISTED_WRITE); + return; + } + + query_result.descriptor->WriteRemoteDescriptor( + value, base::Bind(&WebBluetoothServiceImpl::OnDescriptorWriteValueSuccess, + weak_ptr_factory_.GetWeakPtr(), callback), + base::Bind(&WebBluetoothServiceImpl::OnDescriptorWriteValueFailed, + weak_ptr_factory_.GetWeakPtr(), callback)); +} + void WebBluetoothServiceImpl::RequestDeviceImpl( blink::mojom::WebBluetoothRequestDeviceOptionsPtr options, const RequestDeviceCallback& callback, @@ -993,6 +1036,22 @@ base::nullopt /* value */); } +void WebBluetoothServiceImpl::OnDescriptorWriteValueSuccess( + const RemoteDescriptorWriteValueCallback& callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + // TODO(667319): We are reporting failures to UMA but not reporting successes + callback.Run(blink::mojom::WebBluetoothResult::SUCCESS); +} + +void WebBluetoothServiceImpl::OnDescriptorWriteValueFailed( + const RemoteDescriptorWriteValueCallback& callback, + device::BluetoothRemoteGattService::GattErrorCode error_code) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + RecordDescriptorWriteValueOutcome(UMAGATTOperationOutcome::SUCCESS); + callback.Run(TranslateGATTErrorAndRecord(error_code, + UMAGATTOperation::DESCRIPTOR_WRITE)); +} + CacheQueryResult WebBluetoothServiceImpl::QueryCacheForDevice( const WebBluetoothDeviceId& device_id) { const std::string& device_address =
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.h b/content/browser/bluetooth/web_bluetooth_service_impl.h index c8a4c59..21660329 100644 --- a/content/browser/bluetooth/web_bluetooth_service_impl.h +++ b/content/browser/bluetooth/web_bluetooth_service_impl.h
@@ -136,6 +136,10 @@ void RemoteDescriptorReadValue( const std::string& characteristic_instance_id, const RemoteDescriptorReadValueCallback& callback) override; + void RemoteDescriptorWriteValue( + const std::string& descriptor_instance_id, + const std::vector<uint8_t>& value, + const RemoteDescriptorWriteValueCallback& callback) override; void RequestDeviceImpl( blink::mojom::WebBluetoothRequestDeviceOptionsPtr options, @@ -206,6 +210,13 @@ const RemoteDescriptorReadValueCallback& callback, device::BluetoothRemoteGattService::GattErrorCode error_code); + // Callbacks for BluetoothRemoteGattDescriptor::WriteRemoteDescriptor. + void OnDescriptorWriteValueSuccess( + const RemoteDescriptorWriteValueCallback& callback); + void OnDescriptorWriteValueFailed( + const RemoteDescriptorWriteValueCallback& callback, + device::BluetoothRemoteGattService::GattErrorCode error_code); + // Functions to query the platform cache for the bluetooth object. // result.outcome == CacheQueryOutcome::SUCCESS if the object was found in the // cache. Otherwise result.outcome that can used to record the outcome and
diff --git a/content/browser/frame_host/frame_tree_node.cc b/content/browser/frame_host/frame_tree_node.cc index 57d92fd..bfa7e4a 100644 --- a/content/browser/frame_host/frame_tree_node.cc +++ b/content/browser/frame_host/frame_tree_node.cc
@@ -7,6 +7,7 @@ #include <queue> #include <utility> +#include "base/lazy_instance.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h"
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index f0f2743d..c61d97f 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc
@@ -57,7 +57,6 @@ #include "content/public/common/service_names.mojom.h" #include "gpu/command_buffer/service/gpu_preferences.h" #include "gpu/command_buffer/service/gpu_switches.h" -#include "gpu/config/gpu_driver_bug_list.h" #include "gpu/ipc/host/shader_disk_cache.h" #include "gpu/ipc/service/switches.h" #include "ipc/ipc_channel_handle.h" @@ -1057,11 +1056,6 @@ browser_command_line, switches::kGLSwitchesCopiedFromGpuProcessHost, switches::kGLSwitchesCopiedFromGpuProcessHostNumSwitches); - std::vector<const char*> gpu_workarounds; - gpu::GpuDriverBugList::AppendAllWorkarounds(&gpu_workarounds); - cmd_line->CopySwitchesFrom(browser_command_line, - gpu_workarounds.data(), gpu_workarounds.size()); - GetContentClient()->browser()->AppendExtraCommandLineSwitches( cmd_line.get(), process_->GetData().id);
diff --git a/content/browser/renderer_host/media/audio_input_device_manager.cc b/content/browser/renderer_host/media/audio_input_device_manager.cc index aa47a6d..d2db4e1 100644 --- a/content/browser/renderer_host/media/audio_input_device_manager.cc +++ b/content/browser/renderer_host/media/audio_input_device_manager.cc
@@ -153,8 +153,7 @@ out.device.matched_output_device_id = audio_manager_->GetAssociatedOutputDeviceID(info.device.id); - if (info.device.type == MEDIA_TAB_AUDIO_CAPTURE || - base::CommandLine::ForCurrentProcess()->HasSwitch( + if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kUseFakeDeviceForMediaStream)) { // Don't need to query the hardware information if using fake device. input_params.sample_rate = 44100; @@ -164,6 +163,17 @@ out.device.matched_output.channel_layout = media::CHANNEL_LAYOUT_STEREO; } } else { + // TODO(tommi): As is, we hit this code path when device.type is + // MEDIA_TAB_AUDIO_CAPTURE and the device id is not a device that + // the AudioManager can know about. This currently does not fail because + // the implementation of GetInputStreamParameters returns valid parameters + // by default for invalid devices. That behavior is problematic because it + // causes other parts of the code to attempt to open truly invalid or + // missing devices and falling back on alternate devices (and likely fail + // twice in a row). Tab audio capture should not pass through here and + // GetInputStreamParameters should return invalid parameters for invalid + // devices. + // Get the preferred sample rate and channel configuration for the // audio device. media::AudioParameters params =
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/PhoneNumberDetectionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/PhoneNumberDetectionTest.java index f292a16..ce9bf63 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/PhoneNumberDetectionTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/PhoneNumberDetectionTest.java
@@ -146,6 +146,7 @@ @MediumTest @Feature({"ContentDetection", "TabContents"}) + @DisabledTest(message = "crbug.com/673279") @CommandLineFlags.Add(ContentSwitches.NETWORK_COUNTRY_ISO + "=US") public void testLocalUSNumbers() throws Throwable { startActivityWithTestUrl(
diff --git a/content/renderer/presentation/presentation_connection_proxy_unittest.cc b/content/renderer/presentation/presentation_connection_proxy_unittest.cc index 03f0bcc5..1a94178 100644 --- a/content/renderer/presentation/presentation_connection_proxy_unittest.cc +++ b/content/renderer/presentation/presentation_connection_proxy_unittest.cc
@@ -98,7 +98,7 @@ base::RunLoop run_loop; EXPECT_CALL(*receiver_connection_, didReceiveBinaryMessage(_, _)) .WillOnce(::testing::Invoke( - [this, &expected_data](const uint8_t* data, size_t length) { + [&expected_data](const uint8_t* data, size_t length) { std::vector<uint8_t> message_data(data, data + length); EXPECT_EQ(expected_data, message_data); }));
diff --git a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc index cf5f88a6..4df4e49c 100644 --- a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc +++ b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
@@ -759,21 +759,31 @@ callback.Run(value); })); + ON_CALL(*user_description, WriteRemoteDescriptor(_, _, _)) + .WillByDefault(RunCallback<1 /* success_callback */>()); + auto client_config = base::MakeUnique<NiceMockBluetoothGattDescriptor>( measurement_interval.get(), "gatt.client_characteristic_configuration", BluetoothUUID(kClientConfigUUID), false /* is_local */, device::BluetoothRemoteGattCharacteristic::PROPERTY_READ | device::BluetoothRemoteGattCharacteristic::PROPERTY_WRITE); + // Crash if WriteRemoteDescriptor called. Not using GoogleMock's Expect + // because this is used in layout tests that may not report a mock + // expectation. + ON_CALL(*client_config, WriteRemoteDescriptor(_, _, _)) + .WillByDefault( + Invoke([](const std::vector<uint8_t>&, const base::Closure&, + const BluetoothRemoteGattDescriptor::ErrorCallback&) { + NOTREACHED(); + })); + auto no_read_descriptor = base::MakeUnique<NiceMockBluetoothGattDescriptor>( measurement_interval.get(), kBlocklistedReadDescriptorUUID, BluetoothUUID(kBlocklistedReadDescriptorUUID), false, device::BluetoothRemoteGattCharacteristic::PROPERTY_READ | device::BluetoothRemoteGattCharacteristic::PROPERTY_WRITE); - std::vector<uint8_t> value(1); - value[0] = false; - // Crash if ReadRemoteDescriptor called. Not using GoogleMock's Expect // because this is used in layout tests that may not report a mock // expectation @@ -1132,6 +1142,28 @@ } })); + ON_CALL(*user_descriptor, WriteRemoteDescriptor(_, _, _)) + .WillByDefault(Invoke([adapter_ptr, device_ptr, user_descriptor_ptr, + disconnect, succeeds]( + const std::vector<uint8_t>& value, const base::Closure& callback, + const BluetoothRemoteGattDescriptor::ErrorCallback& error_callback) { + base::Closure pending; + if (succeeds) { + pending = callback; + } else { + pending = base::Bind(error_callback, + BluetoothRemoteGattService::GATT_ERROR_FAILED); + } + device_ptr->PushPendingCallback(pending); + if (disconnect) { + device_ptr->SetConnected(false); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&NotifyDeviceChanged, base::RetainedRef(adapter_ptr), + device_ptr)); + } + })); + measurement_interval->AddMockDescriptor(std::move(user_descriptor)); health_thermometer->AddMockCharacteristic(std::move(measurement_interval)); @@ -1731,6 +1763,9 @@ ON_CALL(*error_descriptor, ReadRemoteDescriptor(_, _)) .WillByDefault(RunCallback<1 /* error_callback */>(error_code)); + ON_CALL(*error_descriptor, WriteRemoteDescriptor(_, _, _)) + .WillByDefault(RunCallback<2 /* error_callback */>(error_code)); + characteristic->AddMockDescriptor(std::move(error_descriptor)); return characteristic;
diff --git a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h index a770c8b8..5343b92 100644 --- a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h +++ b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h
@@ -343,12 +343,16 @@ // BluetoothRemoteGattCharacteristic::PROPERTY_READ // - Descriptors (if |addDescriptors| input is true) // - User Description (2901) + // - Mock Functions: + // - Read: Calls success callback with + // "gatt.characteristic_user_description". + // - Write: Calls success callback. // - Client Characteristic Configuration (2902) // Note: This descriptor is blocklisted for writes. // - bad2ddcf-60db-45cd-bef9-fd72b153cf7c // A test descriptor that is blocklisted. // - bad3ec61-3cc3-4954-9702-7977df514114 - // A test descriptor that is exclude read.. + // A test descriptor that is exclude read. static scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>> GetDisconnectingHealthThermometer(bool add_descriptors); @@ -400,6 +404,13 @@ // succeeding callback, otherwise it saves a failing callback. // This calback is run during CreateGattConnection. If // |disconnect| is true disconnects the device. + // - user_descriptor + // - Operations read / write nearly identical to the read and + // write methods of the characteristic. + // - Read: If |succeeds| is true, saves a succeeding callback, + // otherwise it saves a failing callback. + // - Write: If |succeeds| is true, saves a succeeding callback + // otherwise it saves a failing callback. // - CreateGattConnection: Runs success callback with a new GATT // connection and runs any pending GATT operation callbacks. static scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>>
diff --git a/content/test/gpu/gpu_tests/gpu_process_integration_test.py b/content/test/gpu/gpu_tests/gpu_process_integration_test.py index 225c3dd..89691ed 100644 --- a/content/test/gpu/gpu_tests/gpu_process_integration_test.py +++ b/content/test/gpu/gpu_tests/gpu_process_integration_test.py
@@ -115,8 +115,7 @@ ('GpuProcess_identify_active_gpu2', 'chrome:gpu'), ('GpuProcess_identify_active_gpu3', 'chrome:gpu'), ('GpuProcess_identify_active_gpu4', 'chrome:gpu'), - ('GpuProcess_software_gpu_process', 'about:blank'), - ('GpuProcess_disabling_workarounds_works', 'chrome:gpu')) + ('GpuProcess_software_gpu_process', 'about:blank')) # The earlier has_transparent_visuals_gpu_process and # no_transparent_visuals_gpu_process tests became no-ops in @@ -527,17 +526,6 @@ self._Navigate(test_path) self._VerifyGpuProcessPresent() - def _GpuProcess_disabling_workarounds_works(self, test_path): - self.RestartBrowserIfNecessaryWithArgs([ - '--gpu-testing-vendor-id=0xbad9', - '--gpu-testing-device-id=0xbad9', - '--use_gpu_driver_workaround_for_testing=0']) - self._Navigate(test_path) - workarounds, _ = ( - self._CompareAndCaptureDriverBugWorkarounds()) - if 'use_gpu_driver_workaround_for_testing' in workarounds: - self.fail('use_gpu_driver_workaround_for_testing erroneously present') - def load_tests(loader, tests, pattern): del loader, tests, pattern # Unused. return gpu_integration_test.LoadAllTestsInModule(sys.modules[__name__])
diff --git a/content/utility/in_process_utility_thread.cc b/content/utility/in_process_utility_thread.cc index 426326b..8417c599 100644 --- a/content/utility/in_process_utility_thread.cc +++ b/content/utility/in_process_utility_thread.cc
@@ -4,6 +4,7 @@ #include "content/utility/in_process_utility_thread.h" +#include "base/lazy_instance.h" #include "base/location.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h"
diff --git a/extensions/browser/PRESUBMIT.py b/extensions/browser/PRESUBMIT.py index 15f8d93..5bd5fad 100644 --- a/extensions/browser/PRESUBMIT.py +++ b/extensions/browser/PRESUBMIT.py
@@ -34,10 +34,27 @@ results += _CreateHistogramValueChecker(input_api, output_api, path).Run() return results +def _RunHistogramChecks(input_api, output_api, histogram_name): + try: + # Setup sys.path so that we can call histrogram code + import sys + original_sys_path = sys.path + sys.path = sys.path + [input_api.os_path.join( + input_api.change.RepositoryRoot(), + 'tools', 'metrics', 'histograms')] + + import presubmit_bad_message_reasons + return presubmit_bad_message_reasons.PrecheckBadMessage(input_api, + output_api, histogram_name) + except: + return [output_api.PresubmitError('Could not verify histogram!')] + finally: + sys.path = original_sys_path def CheckChangeOnUpload(input_api, output_api): results = [] results += _RunHistogramValueCheckers(input_api, output_api) results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api) + results += _RunHistogramChecks(input_api, output_api, + "BadMessageReasonExtensions") return results -
diff --git a/extensions/browser/guest_view/extension_options/extension_options_guest.cc b/extensions/browser/guest_view/extension_options/extension_options_guest.cc index 12dd8f3..2e466c92 100644 --- a/extensions/browser/guest_view/extension_options/extension_options_guest.cc +++ b/extensions/browser/guest_view/extension_options/extension_options_guest.cc
@@ -11,7 +11,7 @@ #include "components/crx_file/id_util.h" #include "components/guest_view/browser/guest_view_event.h" #include "components/guest_view/browser/guest_view_manager.h" -#include "content/public/browser/navigation_details.h" +#include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/site_instance.h" #include "content/public/browser/web_contents.h" @@ -220,20 +220,21 @@ return false; } -void ExtensionOptionsGuest::DidNavigateMainFrame( - const content::LoadCommittedDetails& details, - const content::FrameNavigateParams& params) { - if (attached()) { - auto* guest_zoom_controller = - zoom::ZoomController::FromWebContents(web_contents()); - guest_zoom_controller->SetZoomMode( - zoom::ZoomController::ZOOM_MODE_ISOLATED); - SetGuestZoomLevelToMatchEmbedder(); +void ExtensionOptionsGuest::DidFinishNavigation( + content::NavigationHandle* navigation_handle) { + if (!navigation_handle->IsInMainFrame() || + !navigation_handle->HasCommitted() || !attached()) { + return; + } - if (!url::IsSameOriginWith(params.url, options_page_)) { - bad_message::ReceivedBadMessage(web_contents()->GetRenderProcessHost(), - bad_message::EOG_BAD_ORIGIN); - } + auto* guest_zoom_controller = + zoom::ZoomController::FromWebContents(web_contents()); + guest_zoom_controller->SetZoomMode(zoom::ZoomController::ZOOM_MODE_ISOLATED); + SetGuestZoomLevelToMatchEmbedder(); + + if (!url::IsSameOriginWith(navigation_handle->GetURL(), options_page_)) { + bad_message::ReceivedBadMessage(web_contents()->GetRenderProcessHost(), + bad_message::EOG_BAD_ORIGIN); } }
diff --git a/extensions/browser/guest_view/extension_options/extension_options_guest.h b/extensions/browser/guest_view/extension_options/extension_options_guest.h index 5b0505c..b3b714e 100644 --- a/extensions/browser/guest_view/extension_options/extension_options_guest.h +++ b/extensions/browser/guest_view/extension_options/extension_options_guest.h
@@ -57,8 +57,7 @@ content::SessionStorageNamespace* session_storage_namespace) final; // content::WebContentsObserver implementation. - void DidNavigateMainFrame(const content::LoadCommittedDetails& details, - const content::FrameNavigateParams& params) final; + void DidFinishNavigation(content::NavigationHandle* navigation_handle) final; std::unique_ptr<extensions::ExtensionOptionsGuestDelegate> extension_options_guest_delegate_;
diff --git a/extensions/common/feature_switch.cc b/extensions/common/feature_switch.cc index 84eaa904..4d1f414 100644 --- a/extensions/common/feature_switch.cc +++ b/extensions/common/feature_switch.cc
@@ -20,8 +20,6 @@ const char kLoadMediaRouterComponentExtensionFlag[] = "load-media-router-component-extension"; -const char kExtensionActionRedesignExperiment[] = "ExtensionActionRedesign"; - class CommonSwitches { public: CommonSwitches() @@ -42,9 +40,7 @@ error_console(switches::kErrorConsole, FeatureSwitch::DEFAULT_DISABLED), enable_override_bookmarks_ui(switches::kEnableOverrideBookmarksUI, FeatureSwitch::DEFAULT_DISABLED), - extension_action_redesign(switches::kExtensionActionRedesign, - kExtensionActionRedesignExperiment, - FeatureSwitch::DEFAULT_ENABLED), + extension_action_redesign(nullptr, FeatureSwitch::DEFAULT_ENABLED), scripts_require_action(switches::kScriptsRequireAction, FeatureSwitch::DEFAULT_DISABLED), embedded_extension_options(switches::kEmbeddedExtensionOptions,
diff --git a/extensions/common/switches.cc b/extensions/common/switches.cc index e867a3a6..3a5bc085 100644 --- a/extensions/common/switches.cc +++ b/extensions/common/switches.cc
@@ -35,11 +35,6 @@ const char kEnableExperimentalExtensionApis[] = "enable-experimental-extension-apis"; -// Hack so that feature switch can work with about_flags. See -// kEnableScriptsRequireAction. -const char kEnableExtensionActionRedesign[] = - "enable-extension-action-redesign"; - // Enables extensions to hide bookmarks UI elements. const char kEnableOverrideBookmarksUI[] = "enable-override-bookmarks-ui"; @@ -50,9 +45,6 @@ // them in the chrome:extensions page. const char kErrorConsole[] = "error-console"; -// Whether to switch to extension action redesign mode (experimental). -const char kExtensionActionRedesign[] = "extension-action-redesign"; - // Marks a renderer as extension process. const char kExtensionProcess[] = "extension-process";
diff --git a/extensions/common/switches.h b/extensions/common/switches.h index 764aa99..90a142f 100644 --- a/extensions/common/switches.h +++ b/extensions/common/switches.h
@@ -18,11 +18,9 @@ extern const char kEmbeddedExtensionOptions[]; extern const char kEnableEmbeddedExtensionOptions[]; extern const char kEnableExperimentalExtensionApis[]; -extern const char kEnableExtensionActionRedesign[]; extern const char kEnableOverrideBookmarksUI[]; extern const char kEnableBLEAdvertising[]; extern const char kErrorConsole[]; -extern const char kExtensionActionRedesign[]; extern const char kExtensionProcess[]; extern const char kExtensionsOnChromeURLs[]; extern const char kForceDevModeHighlighting[];
diff --git a/gpu/config/gpu_driver_bug_list.cc b/gpu/config/gpu_driver_bug_list.cc index edd9dcf..7ab68a10 100644 --- a/gpu/config/gpu_driver_bug_list.cc +++ b/gpu/config/gpu_driver_bug_list.cc
@@ -94,17 +94,5 @@ } } -// static -void GpuDriverBugList::AppendAllWorkarounds( - std::vector<const char*>* workarounds) { - workarounds->resize(workarounds->size() + - NUMBER_OF_GPU_DRIVER_BUG_WORKAROUND_TYPES); - -#define GPU_OP(type, name) workarounds->push_back(#name); - GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP) -#undef GPU_OP -} - - } // namespace gpu
diff --git a/gpu/config/gpu_driver_bug_list.h b/gpu/config/gpu_driver_bug_list.h index 0ec839e..8db219f 100644 --- a/gpu/config/gpu_driver_bug_list.h +++ b/gpu/config/gpu_driver_bug_list.h
@@ -28,11 +28,6 @@ std::set<int>* workarounds, const base::CommandLine& command_line); - // Append |workarounds| with the full list of workarounds. - // This is needed for correctly passing flags down from - // the browser process to the GPU process. - static void AppendAllWorkarounds(std::vector<const char*>* workarounds); - private: GpuDriverBugList();
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc index 2ff6190a..dc2c7a8 100644 --- a/gpu/config/gpu_driver_bug_list_json.cc +++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -19,7 +19,7 @@ { "name": "gpu driver bug list", // Please update the version number whenever you change this file. - "version": "9.30", + "version": "9.29", "entries": [ { "id": 1, @@ -2324,9 +2324,6 @@ "use_virtualized_gl_contexts" ] }, -) // LONG_STRING_CONST macro -// Avoid C2026 (string too big) error on VisualStudio. -LONG_STRING_CONST( { "id": 214, "description": "Certain versions of Qualcomm driver don't setup scissor state correctly when FBO0 is bound.", @@ -2336,16 +2333,6 @@ "features": [ "force_update_scissor_state_when_binding_fbo0" ] - }, - { - "id": 215, - "description": "Fake no-op GPU driver bug workaround for testing", - "cr_bugs": [682912], - "vendor_id": "0xbad9", - "device_id": ["0xbad9"], - "features": [ - "use_gpu_driver_workaround_for_testing" - ] } ] // Please update the version number at beginning of this file whenever you
diff --git a/ios/web/PRESUBMIT.py b/ios/PRESUBMIT.py similarity index 81% rename from ios/web/PRESUBMIT.py rename to ios/PRESUBMIT.py index 3d39a554..07c61c0c 100644 --- a/ios/web/PRESUBMIT.py +++ b/ios/PRESUBMIT.py
@@ -1,8 +1,8 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. +# Copyright 2017 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Presubmit script for ios/web. +"""Presubmit script for ios. See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for more details about the presubmit API built into depot_tools.
diff --git a/ios/chrome/PRESUBMIT.py b/ios/chrome/PRESUBMIT.py deleted file mode 100644 index 18f3a4f..0000000 --- a/ios/chrome/PRESUBMIT.py +++ /dev/null
@@ -1,14 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Presubmit script for ios/chrome. - -See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts -for more details about the presubmit API built into depot_tools. -""" - -def CheckChangeOnUpload(input_api, output_api): - results = [] - results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api) - return results
diff --git a/ios/chrome/browser/dom_distiller/dom_distiller_service_factory.cc b/ios/chrome/browser/dom_distiller/dom_distiller_service_factory.cc index 918d4e1..c6decb7 100644 --- a/ios/chrome/browser/dom_distiller/dom_distiller_service_factory.cc +++ b/ios/chrome/browser/dom_distiller/dom_distiller_service_factory.cc
@@ -74,19 +74,6 @@ std::unique_ptr<KeyedService> DomDistillerServiceFactory::BuildServiceInstanceFor( web::BrowserState* context) const { - scoped_refptr<base::SequencedTaskRunner> background_task_runner = - web::WebThread::GetBlockingPool()->GetSequencedTaskRunner( - web::WebThread::GetBlockingPool()->GetSequenceToken()); - - std::unique_ptr<leveldb_proto::ProtoDatabaseImpl<ArticleEntry>> db = - base::MakeUnique<leveldb_proto::ProtoDatabaseImpl<ArticleEntry>>( - background_task_runner); - - base::FilePath database_dir( - context->GetStatePath().Append(FILE_PATH_LITERAL("Articles"))); - - std::unique_ptr<DomDistillerStore> dom_distiller_store = - base::MakeUnique<DomDistillerStore>(std::move(db), database_dir); std::unique_ptr<DistillerPageFactory> distiller_page_factory = base::MakeUnique<DistillerPageFactoryIOS>(context); @@ -104,8 +91,8 @@ ios::ChromeBrowserState::FromBrowserState(context)->GetPrefs()); return base::MakeUnique<DomDistillerKeyedService>( - std::move(dom_distiller_store), std::move(distiller_factory), - std::move(distiller_page_factory), std::move(distilled_page_prefs)); + nullptr, std::move(distiller_factory), std::move(distiller_page_factory), + std::move(distilled_page_prefs)); } web::BrowserState* DomDistillerServiceFactory::GetBrowserStateToUse(
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm index 96d7bb9..ff9f45e 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_view_controller.mm
@@ -578,7 +578,7 @@ NSArray* items = [self.collectionViewModel itemsInSectionWithIdentifier:sectionIdentifier]; if ([items count] != map.size()) - return NO; + return YES; NSInteger index = 0; ItemsMapByDate::const_reverse_iterator iterator = map.rbegin();
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.h b/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.h index ca03cc62..cfed23d9 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.h +++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.h
@@ -46,6 +46,13 @@ // Sets the cell's appearance using information in |tab|. // The delegate needs to be set before calling this method. - (void)setAppearanceForTab:(Tab*)tab cellSize:(CGSize)cellSize; + +// PLACEHOLDER: Sets the cell's appearance using information in |title| and +// |favicon|. +- (void)setAppearanceForTabTitle:(NSString*)title + favicon:(UIImage*)favicon + cellSize:(CGSize)cellSize; + // Sets the cell's appearance depending on |type|. - (void)setSessionType:(TabSwitcherSessionType)type;
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.mm b/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.mm index bad9ca2..bf3f9f2 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.mm
@@ -242,6 +242,22 @@ }]; } +- (void)setAppearanceForTabTitle:(NSString*)title + favicon:(UIImage*)favicon + cellSize:(CGSize)cellSize { + [_titleLabel setText:title]; + [_snapshotButton setAccessibilityIdentifier: + [NSString stringWithFormat:@"%@_button", title]]; + [self contentView].accessibilityLabel = title; + if (favicon) { + [_favicon setImage:favicon]; + } else { + [_favicon setImage:NativeImage(IDR_IOS_OMNIBOX_HTTP)]; + } + + // PLACEHOLDER: Set snapshot here. +} + - (void)setSessionType:(TabSwitcherSessionType)type { UIColor* topBarBackgroundColor; UIColor* closeButtonTintColor;
diff --git a/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn b/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn index 74bd8bee..38efb26 100644 --- a/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn +++ b/ios/clean/chrome/browser/ui/tab_grid/BUILD.gn
@@ -39,6 +39,7 @@ deps = [ "//base", + "//ios/chrome/browser/ui/tab_switcher", "//ios/clean/chrome/browser/ui/actions", "//ios/clean/chrome/browser/ui/animators", "//ios/clean/chrome/browser/ui/commands",
diff --git a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm index f91f66e..6948934 100644 --- a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm +++ b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
@@ -51,7 +51,7 @@ [super setBrowserState:browserState]; // PLACEHOLDER: Generate a tab group with four empty tabs. self.tabGroup = - [TabGroup tabGroupWithEmptyTabCount:4 forBrowserState:self.browserState]; + [TabGroup tabGroupWithEmptyTabCount:7 forBrowserState:self.browserState]; } #pragma mark - BrowserCoordinator @@ -81,7 +81,7 @@ WebMediator* tab = [self.tabGroup tabAtIndex:index]; GURL url = tab.webState->GetVisibleURL(); NSString* urlText = @"<New Tab>"; - if (!url.is_valid()) { + if (url.is_valid()) { urlText = base::SysUTF8ToNSString(url.spec()); } return urlText;
diff --git a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm index 8ebf91b..0d20e73 100644 --- a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm +++ b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -9,19 +9,19 @@ #import "ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.h" #include "base/mac/foundation_util.h" +#import "ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.h" +#import "ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_collection_view_layout.h" #import "ios/clean/chrome/browser/ui/actions/settings_actions.h" #import "ios/clean/chrome/browser/ui/actions/tab_grid_actions.h" #import "ios/clean/chrome/browser/ui/commands/settings_commands.h" #import "ios/clean/chrome/browser/ui/commands/tab_commands.h" #import "ios/clean/chrome/browser/ui/commands/tab_grid_commands.h" -#import "ios/clean/chrome/browser/ui/tab_grid/tab_grid_tab_cell.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif namespace { -NSString* const kTabGridCellIdentifier = @"tabGridCell"; const CGFloat kSpace = 20; const CGFloat kTabSize = 150; } @@ -29,7 +29,8 @@ @interface TabGridViewController ()<SettingsActions, TabGridActions, UICollectionViewDataSource, - UICollectionViewDelegate> + UICollectionViewDelegate, + SessionCellDelegate> @property(nonatomic, weak) UICollectionView* grid; @end @@ -68,8 +69,8 @@ [settings.centerYAnchor constraintEqualToAnchor:stripe.centerYAnchor] ]]; - UICollectionViewFlowLayout* layout = - [[UICollectionViewFlowLayout alloc] init]; + TabSwitcherPanelCollectionViewLayout* layout = + [[TabSwitcherPanelCollectionViewLayout alloc] init]; layout.minimumLineSpacing = kSpace; layout.minimumInteritemSpacing = kSpace; layout.sectionInset = UIEdgeInsetsMake(kSpace, kSpace, kSpace, kSpace); @@ -84,8 +85,8 @@ self.grid = grid; self.grid.dataSource = self; self.grid.delegate = self; - [self.grid registerClass:[TabGridTabCell class] - forCellWithReuseIdentifier:kTabGridCellIdentifier]; + [self.grid registerClass:[TabSwitcherLocalSessionCell class] + forCellWithReuseIdentifier:[TabSwitcherLocalSessionCell identifier]]; [NSLayoutConstraint activateConstraints:@[ [self.grid.topAnchor constraintEqualToAnchor:stripe.bottomAnchor], @@ -113,23 +114,19 @@ - (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath*)indexPath { - TabGridTabCell* cell = - base::mac::ObjCCastStrict<TabGridTabCell>([collectionView - dequeueReusableCellWithReuseIdentifier:kTabGridCellIdentifier + TabSwitcherLocalSessionCell* cell = + base::mac::ObjCCastStrict<TabSwitcherLocalSessionCell>([collectionView + dequeueReusableCellWithReuseIdentifier: + [TabSwitcherLocalSessionCell identifier] forIndexPath:indexPath]); - cell.contentView.backgroundColor = [UIColor purpleColor]; - cell.selected = YES; - cell.label.text = [self.dataSource titleAtIndex:indexPath.item]; + cell.delegate = self; + [cell setSessionType:TabSwitcherSessionType::REGULAR_SESSION]; + [cell setAppearanceForTabTitle:[self.dataSource titleAtIndex:indexPath.item] + favicon:nil + cellSize:CGSizeZero]; return cell; } -#pragma mark - UICollectionViewDelegate methods - -- (void)collectionView:(UICollectionView*)collectionView - didSelectItemAtIndexPath:(NSIndexPath*)indexPath { - [self.tabCommandHandler showTabAtIndexPath:indexPath]; -} - #pragma mark - ZoomTransitionDelegate methods - (CGRect)rectForZoomWithKey:(NSObject*)key inView:(UIView*)view { @@ -152,4 +149,19 @@ [self.tabGridCommandHandler showTabGrid]; } +#pragma mark - SessionCellDelegate + +- (TabSwitcherCache*)tabSwitcherCache { + // PLACEHOLDER: return image cache. + return nil; +} + +- (void)cellPressed:(UICollectionViewCell*)cell { + [self.tabCommandHandler showTabAtIndexPath:[self.grid indexPathForCell:cell]]; +} + +- (void)deleteButtonPressedForCell:(UICollectionViewCell*)cell { + // PLACEHOLDER: handle close tab button. +} + @end
diff --git a/ios/showcase/tab_grid/sc_tab_grid_egtest.mm b/ios/showcase/tab_grid/sc_tab_grid_egtest.mm index 68a4ad0a..e343032 100644 --- a/ios/showcase/tab_grid/sc_tab_grid_egtest.mm +++ b/ios/showcase/tab_grid/sc_tab_grid_egtest.mm
@@ -20,7 +20,7 @@ - (void)testLaunchAndTappingCell { [[EarlGrey selectElementWithMatcher:grey_text(@"TabGridViewController")] performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:grey_text(@"Tab 0")] + [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Tab 0_button")] performAction:grey_tap()]; [[EarlGrey selectElementWithMatcher:grey_text(@"TabCommands")] assertWithMatcher:grey_notNil()];
diff --git a/ios/showcase/toolbar/BUILD.gn b/ios/showcase/toolbar/BUILD.gn index c9bd5eb41..223a3d11 100644 --- a/ios/showcase/toolbar/BUILD.gn +++ b/ios/showcase/toolbar/BUILD.gn
@@ -8,6 +8,7 @@ "sc_toolbar_coordinator.mm", ] deps = [ + "//ios/clean/chrome/browser/ui/commands", "//ios/clean/chrome/browser/ui/toolbar:toolbar_ui", "//ios/showcase/common", ]
diff --git a/ios/showcase/toolbar/sc_toolbar_coordinator.mm b/ios/showcase/toolbar/sc_toolbar_coordinator.mm index 3291310..939ae29 100644 --- a/ios/showcase/toolbar/sc_toolbar_coordinator.mm +++ b/ios/showcase/toolbar/sc_toolbar_coordinator.mm
@@ -4,19 +4,70 @@ #import "ios/showcase/toolbar/sc_toolbar_coordinator.h" +#import "ios/clean/chrome/browser/ui/commands/toolbar_commands.h" #import "ios/clean/chrome/browser/ui/toolbar/toolbar_view_controller.h" +#import "ios/showcase/common/protocol_alerter.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif +namespace { +// Toolbar height. +CGFloat kToolbarHeight = 50.0f; +} // namespace + +@interface SCToolbarCoordinator () +@property(nonatomic, strong) ProtocolAlerter* alerter; +@end + @implementation SCToolbarCoordinator @synthesize baseViewController = _baseViewController; +@synthesize alerter = _alerter; - (void)start { - ToolbarViewController* viewController = [[ToolbarViewController alloc] init]; - viewController.title = @"Toolbar"; - [self.baseViewController pushViewController:viewController animated:YES]; + self.alerter = [[ProtocolAlerter alloc] + initWithProtocols:@[ @protocol(ToolbarCommands) ]]; + self.alerter.baseViewController = self.baseViewController; + + UIViewController* containerViewController = [[UIViewController alloc] init]; + containerViewController.view.backgroundColor = [UIColor whiteColor]; + containerViewController.title = @"Toolbar"; + + UIView* containerView = [[UIView alloc] init]; + [containerViewController.view addSubview:containerView]; + containerView.backgroundColor = [UIColor redColor]; + containerView.translatesAutoresizingMaskIntoConstraints = NO; + + ToolbarViewController* toolbarViewController = + [[ToolbarViewController alloc] init]; + toolbarViewController.toolbarCommandHandler = + static_cast<id<ToolbarCommands>>(self.alerter); + toolbarViewController.view.translatesAutoresizingMaskIntoConstraints = NO; + [containerViewController addChildViewController:toolbarViewController]; + [containerView addSubview:toolbarViewController.view]; + [toolbarViewController didMoveToParentViewController:containerViewController]; + + [NSLayoutConstraint activateConstraints:@[ + [containerView.heightAnchor constraintEqualToConstant:kToolbarHeight], + [containerView.leadingAnchor + constraintEqualToAnchor:containerViewController.view.leadingAnchor], + [containerView.trailingAnchor + constraintEqualToAnchor:containerViewController.view.trailingAnchor], + [containerView.centerYAnchor + constraintEqualToAnchor:containerViewController.view.centerYAnchor], + [toolbarViewController.view.topAnchor + constraintEqualToAnchor:containerView.topAnchor], + [toolbarViewController.view.bottomAnchor + constraintEqualToAnchor:containerView.bottomAnchor], + [toolbarViewController.view.leadingAnchor + constraintEqualToAnchor:containerView.leadingAnchor], + [toolbarViewController.view.trailingAnchor + constraintEqualToAnchor:containerView.trailingAnchor], + ]]; + + [self.baseViewController pushViewController:containerViewController + animated:YES]; } @end
diff --git a/ios/web_view/public/criwv.h b/ios/web_view/public/criwv.h index a858af2..f90a34a 100644 --- a/ios/web_view/public/criwv.h +++ b/ios/web_view/public/criwv.h
@@ -11,6 +11,7 @@ @protocol CRIWVWebView; // Main interface for the CRIWV library. +__attribute__((visibility("default"))) @interface CRIWV : NSObject // Initializes the CRIWV library. This function should be called from
diff --git a/media/audio/win/audio_manager_win.cc b/media/audio/win/audio_manager_win.cc index b5b262fb..119ac3a2 100644 --- a/media/audio/win/audio_manager_win.cc +++ b/media/audio/win/audio_manager_win.cc
@@ -285,7 +285,14 @@ if (FAILED(hr) || !parameters.IsValid()) { LOG(WARNING) << "Unable to get preferred audio params for " << device_id << " 0x" << std::hex << hr; - return parameters; + // TODO(tommi): We appear to have callers to GetInputStreamParameters that + // rely on getting valid audio parameters returned for an invalid or + // unavailable device. We should track down those code paths (it is likely + // that they actually don't need a real device but depend on the audio + // code path somehow for a configuration - e.g. tab capture). + parameters = + AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, + CHANNEL_LAYOUT_STEREO, 48000, 16, kFallbackBufferSize); } int user_buffer_size = GetUserBufferSize();
diff --git a/storage/browser/quota/quota_manager.cc b/storage/browser/quota/quota_manager.cc index 44ba5f1..489d717 100644 --- a/storage/browser/quota/quota_manager.cc +++ b/storage/browser/quota/quota_manager.cc
@@ -26,6 +26,7 @@ #include "base/strings/string_number_conversions.h" #include "base/sys_info.h" #include "base/task_runner_util.h" +#include "base/threading/thread_restrictions.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "net/base/url_util.h"
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 4089d88..08a66cc1 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -734,21 +734,6 @@ ] } ], - "ExtensionActionRedesign": [ - { - "platforms": [ - "chromeos", - "linux", - "mac", - "win" - ], - "experiments": [ - { - "name": "Enabled" - } - ] - } - ], "ExtensionContentVerification": [ { "platforms": [
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-blocklisted.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/descriptor-is-blocklisted.html similarity index 94% rename from third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-blocklisted.html rename to third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/descriptor-is-blocklisted.html index f33cf80..3964edb 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-blocklisted.html +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/descriptor-is-blocklisted.html
@@ -1,4 +1,3 @@ -<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> <!DOCTYPE html> <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-removed.html index 5fb1b5be..a6060802 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-removed.html +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-removed.html
@@ -6,6 +6,7 @@ <script> 'use strict'; promise_test(() => { + let val = new Uint8Array([1]); return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') .then( () => requestDeviceWithKeyDown(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-fails.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-fails.html index 2b4aea8..a3bc1f11 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-fails.html +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-fails.html
@@ -7,6 +7,7 @@ 'use strict'; promise_test( () => { + let val = new Uint8Array([1]); return setBluetoothFakeAdapter('FailingGATTOperationsAdapter') .then( () => requestDeviceWithKeyDown(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-success.html index 42dbf74..d379600 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-success.html +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-success.html
@@ -7,6 +7,7 @@ 'use strict'; promise_test( () => { + let val = new Uint8Array([1]); let promise; return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') .then(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-error.html index 5a1516f9..c72b5ddc 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-error.html +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-error.html
@@ -6,6 +6,7 @@ <script> promise_test( () => { + let val = new Uint8Array([1]); return setBluetoothFakeAdapter( 'GATTOperationFailsAfterReconnectionAdapter') .then(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-service-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-service-is-removed.html index 2cd9e6d..eb7f24e 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-service-is-removed.html +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-service-is-removed.html
@@ -8,23 +8,21 @@ promise_test(() => { let val = new Uint8Array([1]); return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') - .then( - () => requestDeviceWithKeyDown( - {filters: [{services: ['health_thermometer']}]})) - .then(device => device.gatt.connect()) - .then(gattServer => gattServer.getPrimaryService('health_thermometer')) - .then(service => service.getCharacteristic('measurement_interval')) - .then( - characteristic => characteristic.getDescriptor(user_description.name)) - .then(descriptor => { - return setBluetoothFakeAdapter('MissingServiceHeartRateAdapter') - .then( - () => assert_promise_rejects_with_message( - descriptor.readValue(), - new DOMException( - 'GATT Service no longer exists.', 'InvalidStateError'), - 'Service got removed.')); - }); + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then(characteristic => characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + return setBluetoothFakeAdapter('MissingServiceHeartRateAdapter') + .then(() => assert_promise_rejects_with_message( + descriptor.readValue(), + new DOMException( + 'GATT Service no longer exists.', + 'InvalidStateError'), + 'Service got removed.')); + }); }, 'Service gets removed. Reject with InvalidStateError.'); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-blocklisted.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/descriptor-is-blocklisted.html similarity index 70% copy from third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-blocklisted.html copy to third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/descriptor-is-blocklisted.html index f33cf80..bec0a26ad 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-blocklisted.html +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/descriptor-is-blocklisted.html
@@ -1,4 +1,3 @@ -<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> <!DOCTYPE html> <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> @@ -7,6 +6,7 @@ 'use strict'; promise_test( () => { + let val = new Uint8Array([1]); return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') .then( () => requestDeviceWithKeyDown( @@ -17,16 +17,15 @@ gattServer.getPrimaryService('health_thermometer')) .then(service => service.getCharacteristic('measurement_interval')) .then( - characteristic => characteristic.getDescriptor( - 'bad3ec61-3cc3-4954-9702-7977df514114')) + characteristic => characteristic.getDescriptor(0x2902)) .then(descriptor => { return assert_promise_rejects_with_message( - descriptor.readValue(), + descriptor.writeValue(val), new DOMException( - 'readValue() called on blocklisted object marked exclude-reads. ' + + 'writeValue() called on blocklisted object marked exclude-writes. ' + 'https://goo.gl/4NeimX', 'SecurityError')); })}, - 'Attempt to call readValue on a blocked descriptor must generate a SecurityError'); + 'Attempt to call writeValue on a blocked descriptor must generate a SecurityError'); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-descriptor-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-descriptor-is-removed.html new file mode 100644 index 0000000..ed710b7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-descriptor-is-removed.html
@@ -0,0 +1,32 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(() => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + return setBluetoothFakeAdapter( + 'MissingDescriptorsDisconnectingHealthThermometerAdapter') + .then( + () => assert_promise_rejects_with_message( + descriptor.writeValue(val), + new DOMException( + 'GATT Descriptor no longer exists.', + 'InvalidStateError'), + 'Descriptor got removed.')); + }); +}, 'Descriptor gets removed. Reject with InvalidStateError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-before.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-before.html new file mode 100644 index 0000000..2decfb8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-before.html
@@ -0,0 +1,35 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(() => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['health_thermometer']}], + optionalServices: [request_disconnection_service_uuid] + })) + .then(device => device.gatt.connect()) + .then(gattServer => { + let measurement_interval; + return gattServer.getPrimaryService('health_thermometer') + .then(ht => ht.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(d => user_description = d) + .then(() => get_request_disconnection(gattServer)) + .then(requestDisconnection => requestDisconnection()) + .then( + () => assert_promise_rejects_with_message( + user_description.writeValue(val), + new DOMException( + 'GATT Server is disconnected. Cannot perform GATT operations.', + 'NetworkError'))); + }); +}, 'Device disconnects before writeValue. Reject with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-error.html new file mode 100644 index 0000000..f1f787c6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-error.html
@@ -0,0 +1,39 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('FailingGATTOperationsAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: [errorUUID(0xA0)]}], + optionalServices: [request_disconnection_service_uuid] + })) + .then(device => device.gatt.connect()) + .then(gattServer => { + let error_characteristic; + return gattServer.getPrimaryService(errorUUID(0xA0)) + .then(es => es.getCharacteristic(errorUUID(0xA1))) + .then( + characteristic => characteristic.getDescriptor( + 'gatt.characteristic_user_description')) + .then(d => user_description = d) + .then(() => get_request_disconnection(gattServer)) + .then(requestDisconnection => { + requestDisconnection(); + return assert_promise_rejects_with_message( + user_description.writeValue(val), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + }); + }); + }, + 'Device disconnects during a writeValue call that fails. ' + + 'Reject with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-success.html new file mode 100644 index 0000000..25a49665 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-success.html
@@ -0,0 +1,38 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['health_thermometer']}], + optionalServices: [request_disconnection_service_uuid] + })) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer.getPrimaryService('health_thermometer') + .then(ht => ht.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(d => user_description = d) + .then(() => get_request_disconnection(gattServer)) + .then(requestDisconnection => { + requestDisconnection(); + return assert_promise_rejects_with_message( + user_description.writeValue(val), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + }); + }); + }, + 'Device disconnects during a writeValue call that succeeds. ' + + 'Reject with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-error.html new file mode 100644 index 0000000..9933ca7c --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-error.html
@@ -0,0 +1,40 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter( + 'DisconnectingDuringFailureGATTOperationAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gatt => gatt.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + let disconnected = eventPromise( + descriptor.characteristic.service.device, + 'gattserverdisconnected'); + let promise = assert_promise_rejects_with_message( + descriptor.writeValue(val), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + return disconnected + .then( + () => + descriptor.characteristic.service.device.gatt.connect()) + .then(() => promise); + }); + }, + 'Device reconnects during a writeValue call that fails. Reject ' + + 'with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-success.html new file mode 100644 index 0000000..4251127c --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-success.html
@@ -0,0 +1,40 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter( + 'DisconnectingDuringSuccessGATTOperationAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gatt => gatt.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + let disconnected = eventPromise( + descriptor.characteristic.service.device, + 'gattserverdisconnected'); + let promise = assert_promise_rejects_with_message( + descriptor.writeValue(val), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + return disconnected + .then( + () => + descriptor.characteristic.service.device.gatt.connect()) + .then(() => promise); + }); + }, + 'Device reconnects during a writeValue call that succeeds. Reject ' + + 'with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-before.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-before.html new file mode 100644 index 0000000..31f741d --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-before.html
@@ -0,0 +1,32 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(() => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer.getPrimaryService('health_thermometer') + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + gattServer.disconnect(); + return assert_promise_rejects_with_message( + descriptor.writeValue(val), + new DOMException( + 'GATT Server is disconnected. Cannot perform GATT operations.', + 'NetworkError')); + }); + }); +}, 'disconnect() called before writeValue. Reject with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-error.html new file mode 100644 index 0000000..5d5bc150 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-error.html
@@ -0,0 +1,36 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('FailingGATTOperationsAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: [errorUUID(0xA0)]}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer.getPrimaryService(errorUUID(0xA0)) + .then(service => service.getCharacteristic(errorUUID(0xA1))) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + let promise = assert_promise_rejects_with_message( + descriptor.writeValue(val), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + gattServer.disconnect(); + return promise; + }); + }); + }, + 'disconnect() called during a writeValue call that fails. ' + + 'Reject with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-success.html new file mode 100644 index 0000000..9e857bc --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-success.html
@@ -0,0 +1,38 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer.getPrimaryService('health_thermometer') + .then( + service => + service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + let promise = assert_promise_rejects_with_message( + descriptor.writeValue(val), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + gattServer.disconnect(); + return promise; + }); + }); + }, + 'disconnect() called during a writeValue call that succeeds. ' + + 'Reject with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-fails.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-fails.html new file mode 100644 index 0000000..317a6d0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-fails.html
@@ -0,0 +1,39 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('FailingGATTOperationsAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: [errorUUID(0xA0)]}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService(errorUUID(0xA0))) + .then( + service => { + service.getCharacteristic(errorUUID(0xA1)) + .then(characteristic => { + let tests = Promise.resolve(); + gatt_errors_tests.forEach(testSpec => { + tests = + tests + .then( + () => characteristic.getDescriptor( + testSpec.uuid)) + .then( + descriptor => + assert_promise_rejects_with_message( + descriptor.writeValue(val), + testSpec.error, + testSpec.testName)); + }); + return tests; + })})}, + 'writeValue fails. Should reject with appropriate error.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-error.html new file mode 100644 index 0000000..d237ddcb --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-error.html
@@ -0,0 +1,38 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test( + () => { + let val = new Uint8Array([1]); + let promise; + return setBluetoothFakeAdapter('FailingGATTOperationsAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: [errorUUID(0xA0)]}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService(errorUUID(0xA0))) + .then(service => service.getCharacteristic(errorUUID(0xA1))) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(error_descriptor => { + promise = assert_promise_rejects_with_message( + error_descriptor.writeValue(val), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + // Disconnect called to clear attributeInstanceMap and allow the + // object to get garbage collected. + error_descriptor.characteristic.service.device.gatt.disconnect(); + }) + .then(runGarbageCollection) + .then(() => promise); + }, + 'Garbage Collection ran during a writeValue call that fails. ' + + 'Should not crash.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-success.html new file mode 100644 index 0000000..2b525fc --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-success.html
@@ -0,0 +1,39 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test( + () => { + let val = new Uint8Array([1]); + let promise; + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then( + gattServer => gattServer.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + promise = assert_promise_rejects_with_message( + descriptor.writeValue(val), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + // Disconnect called to clear attributeInstanceMap and allow the + // object to get garbage collected. + descriptor.characteristic.service.device.gatt.disconnect(); + }) + .then(runGarbageCollection) + .then(() => promise); + }, + 'Garbage collection ran during a writeValue call that succeeds. ' + + 'Should not crash.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-error.html new file mode 100644 index 0000000..d7db91f --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-error.html
@@ -0,0 +1,35 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter( + 'GATTOperationFailsAfterReconnectionAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gatt => gatt.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + let promise = assert_promise_rejects_with_message( + descriptor.writeValue(val), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + let gatt = descriptor.characteristic.service.device.gatt; + gatt.disconnect(); + return gatt.connect().then(() => promise); + }); + }, + 'disconnect() and connect() called during a writeValue call that ' + + 'fails. Reject with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-success.html new file mode 100644 index 0000000..f55f7c5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-success.html
@@ -0,0 +1,35 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +promise_test( + () => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter( + 'GATTOperationSucceedsAfterReconnectionAdapter') + .then( + () => requestDeviceWithKeyDown( + {filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gatt => gatt.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then( + characteristic => + characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + let promise = assert_promise_rejects_with_message( + descriptor.writeValue(val), + new DOMException( + 'GATT Server disconnected while performing a GATT operation.', + 'NetworkError')); + let gatt = descriptor.characteristic.service.device.gatt; + gatt.disconnect(); + return gatt.connect().then(() => promise); + }); + }, + 'disconnect() and connect() called during a writeValue call that ' + + 'succeeds. Reject with NetworkError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-service-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-service-is-removed.html new file mode 100644 index 0000000..6cd2690e --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-service-is-removed.html
@@ -0,0 +1,28 @@ +<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py --> +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(() => { + let val = new Uint8Array([1]); + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then(characteristic => characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + return setBluetoothFakeAdapter('MissingServiceHeartRateAdapter') + .then(() => assert_promise_rejects_with_message( + descriptor.writeValue(val), + new DOMException( + 'GATT Service no longer exists.', + 'InvalidStateError'), + 'Service got removed.')); + }); +}, 'Service gets removed. Reject with InvalidStateError.'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/value-too-long.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/value-too-long.html new file mode 100644 index 0000000..3e25af42 --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/value-too-long.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(() => { + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then(characteristic => characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + return assert_promise_rejects_with_message( + descriptor.writeValue(new Uint8Array(513 /* length */)), + new DOMException( + 'Value can\'t exceed 512 bytes.', 'InvalidModificationError'), + 'Value passed was too long.'); + }) + }, 'Trying to write more than 512 bytes should return an error.'); +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/write-succeeds.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/write-succeeds.html new file mode 100644 index 0000000..e741cb6ae --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/write-succeeds.html
@@ -0,0 +1,22 @@ +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(() => { + let length = 1; + let descriptor; + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then(characteristic => characteristic.getDescriptor(user_description.name)) + .then(d => descriptor = d) + .then(() => descriptor.writeValue(new Uint8Array(length))) + .then(() => descriptor.writeValue(new ArrayBuffer(length))) + .then(() => descriptor.writeValue(new DataView(new ArrayBuffer(length)))); + }, 'A regular write request to a writable descriptor should succeed.'); +</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/write-updates-value.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/write-updates-value.html new file mode 100644 index 0000000..cf4706e --- /dev/null +++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/write-updates-value.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(() => { + return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then(characteristic => characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + assert_equals(descriptor.value, null); + let textEncoder = new TextEncoder(); + let newValue = textEncoder.encode('foo'); + return descriptor.writeValue(newValue).then(() => { + assert_array_equals(descriptor.value.buffer, newValue.buffer); + }) + }) +}, 'Succesful read should update descriptor\'s value.'); +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/descriptor-is-blocklisted.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/descriptor-is-blocklisted.js deleted file mode 100644 index 7c93505..0000000 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/descriptor-is-blocklisted.js +++ /dev/null
@@ -1,24 +0,0 @@ -'use strict'; -promise_test( - () => { - return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') - .then( - () => requestDeviceWithKeyDown( - {filters: [{services: ['health_thermometer']}]})) - .then(device => device.gatt.connect()) - .then( - gattServer => - gattServer.getPrimaryService('health_thermometer')) - .then(service => service.getCharacteristic('measurement_interval')) - .then( - characteristic => characteristic.getDescriptor( - 'bad3ec61-3cc3-4954-9702-7977df514114')) - .then(descriptor => { - return assert_promise_rejects_with_message( - descriptor.CALLS([readValue()]), - new DOMException( - 'readValue() called on blocklisted object marked exclude-reads. ' + - 'https://goo.gl/4NeimX', - 'SecurityError')); - })}, - 'Attempt to call FUNCTION_NAME on a blocked descriptor must generate a SecurityError');
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/descriptor-is-removed.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/descriptor-is-removed.js index b9de7ed..968115be 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/descriptor-is-removed.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/descriptor-is-removed.js
@@ -1,5 +1,6 @@ 'use strict'; promise_test(() => { + let val = new Uint8Array([1]); return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') .then( () => requestDeviceWithKeyDown( @@ -14,7 +15,7 @@ 'MissingDescriptorsDisconnectingHealthThermometerAdapter') .then( () => assert_promise_rejects_with_message( - descriptor.CALLS([readValue()]), + descriptor.CALLS([readValue()|writeValue(val)]), new DOMException( 'GATT Descriptor no longer exists.', 'InvalidStateError'),
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-before.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-before.js index cc22a117..26c38f6 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-before.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-before.js
@@ -19,7 +19,7 @@ .then(requestDisconnection => requestDisconnection()) .then( () => assert_promise_rejects_with_message( - user_description.CALLS([readValue()]), + user_description.CALLS([readValue()|writeValue(val)]), new DOMException( 'GATT Server is disconnected. Cannot perform GATT operations.', 'NetworkError')));
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-error.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-error.js index a34ac39d..a5f1a72 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-error.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-error.js
@@ -20,7 +20,7 @@ .then(requestDisconnection => { requestDisconnection(); return assert_promise_rejects_with_message( - user_description.CALLS([readValue()]), + user_description.CALLS([readValue()|writeValue(val)]), new DOMException( 'GATT Server disconnected while performing a GATT operation.', 'NetworkError'));
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-success.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-success.js index 42ff8c7..b06f5146 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-success.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-success.js
@@ -19,7 +19,7 @@ .then(requestDisconnection => { requestDisconnection(); return assert_promise_rejects_with_message( - user_description.CALLS([readValue()]), + user_description.CALLS([readValue()|writeValue(val)]), new DOMException( 'GATT Server disconnected while performing a GATT operation.', 'NetworkError'));
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-error.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-error.js index 721e2ce..7a4f3b38 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-error.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-error.js
@@ -17,7 +17,7 @@ descriptor.characteristic.service.device, 'gattserverdisconnected'); let promise = assert_promise_rejects_with_message( - descriptor.CALLS([readValue()]), + descriptor.CALLS([readValue()|writeValue(val)]), new DOMException( 'GATT Server disconnected while performing a GATT operation.', 'NetworkError'));
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-success.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-success.js index 425ec6f..1ffc823 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-success.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-success.js
@@ -17,7 +17,7 @@ descriptor.characteristic.service.device, 'gattserverdisconnected'); let promise = assert_promise_rejects_with_message( - descriptor.CALLS([readValue()]), + descriptor.CALLS([readValue()|writeValue(val)]), new DOMException( 'GATT Server disconnected while performing a GATT operation.', 'NetworkError'));
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-before.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-before.js index f2b7b9d..42c090c 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-before.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-before.js
@@ -15,7 +15,7 @@ .then(descriptor => { gattServer.disconnect(); return assert_promise_rejects_with_message( - descriptor.CALLS([readValue()]), + descriptor.CALLS([readValue()|writeValue(val)]), new DOMException( 'GATT Server is disconnected. Cannot perform GATT operations.', 'NetworkError'));
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-error.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-error.js index 890a3da..e8516733 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-error.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-error.js
@@ -15,7 +15,7 @@ characteristic.getDescriptor(user_description.name)) .then(descriptor => { let promise = assert_promise_rejects_with_message( - descriptor.CALLS([readValue()]), + descriptor.CALLS([readValue()|writeValue(val)]), new DOMException( 'GATT Server disconnected while performing a GATT operation.', 'NetworkError'));
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-success.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-success.js index 2f764f8..62bb24b 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-success.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-success.js
@@ -17,7 +17,7 @@ characteristic.getDescriptor(user_description.name)) .then(descriptor => { let promise = assert_promise_rejects_with_message( - descriptor.CALLS([readValue()]), + descriptor.CALLS([readValue()|writeValue(val)]), new DOMException( 'GATT Server disconnected while performing a GATT operation.', 'NetworkError'));
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-fails.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-fails.js index 741a419..f9121af61 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-fails.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-fails.js
@@ -1,6 +1,7 @@ 'use strict'; promise_test( () => { + let val = new Uint8Array([1]); return setBluetoothFakeAdapter('FailingGATTOperationsAdapter') .then( () => requestDeviceWithKeyDown( @@ -21,7 +22,7 @@ .then( descriptor => assert_promise_rejects_with_message( - descriptor.CALLS([readValue()]), + descriptor.CALLS([readValue()|writeValue(val)]), testSpec.error, testSpec.testName)); });
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-error.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-error.js index 1fdf14f..250c016f 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-error.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-error.js
@@ -15,7 +15,7 @@ characteristic.getDescriptor(user_description.name)) .then(error_descriptor => { promise = assert_promise_rejects_with_message( - error_descriptor.CALLS([readValue()]), + error_descriptor.CALLS([readValue()|writeValue(val)]), new DOMException( 'GATT Server disconnected while performing a GATT operation.', 'NetworkError'));
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-success.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-success.js index 0d2ae3c..8dad4b49 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-success.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-success.js
@@ -1,6 +1,7 @@ 'use strict'; promise_test( () => { + let val = new Uint8Array([1]); let promise; return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') .then( @@ -15,7 +16,7 @@ characteristic.getDescriptor(user_description.name)) .then(descriptor => { promise = assert_promise_rejects_with_message( - descriptor.CALLS([readValue()]), + descriptor.CALLS([readValue()|writeValue(val)]), new DOMException( 'GATT Server disconnected while performing a GATT operation.', 'NetworkError'));
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-reconnect-during-error.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-reconnect-during-error.js index e9a30a26..3bf5830 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-reconnect-during-error.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-reconnect-during-error.js
@@ -1,5 +1,6 @@ promise_test( () => { + let val = new Uint8Array([1]); return setBluetoothFakeAdapter( 'GATTOperationFailsAfterReconnectionAdapter') .then( @@ -13,7 +14,7 @@ characteristic.getDescriptor(user_description.name)) .then(descriptor => { let promise = assert_promise_rejects_with_message( - descriptor.CALLS([readValue()]), + descriptor.CALLS([readValue()|writeValue(val)]), new DOMException( 'GATT Server disconnected while performing a GATT operation.', 'NetworkError'));
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-reconnect-during-success.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-reconnect-during-success.js index c82a267..54c0d89 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-reconnect-during-success.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/io-op-reconnect-during-success.js
@@ -14,7 +14,7 @@ characteristic.getDescriptor(user_description.name)) .then(descriptor => { let promise = assert_promise_rejects_with_message( - descriptor.CALLS([readValue()]), + descriptor.CALLS([readValue()|writeValue(val)]), new DOMException( 'GATT Server disconnected while performing a GATT operation.', 'NetworkError'));
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/service-is-removed.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/service-is-removed.js index a6058a9..d3486db 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/service-is-removed.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/service-is-removed.js
@@ -2,21 +2,19 @@ promise_test(() => { let val = new Uint8Array([1]); return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') - .then( - () => requestDeviceWithKeyDown( - {filters: [{services: ['health_thermometer']}]})) - .then(device => device.gatt.connect()) - .then(gattServer => gattServer.getPrimaryService('health_thermometer')) - .then(service => service.getCharacteristic('measurement_interval')) - .then( - characteristic => characteristic.getDescriptor(user_description.name)) - .then(descriptor => { - return setBluetoothFakeAdapter('MissingServiceHeartRateAdapter') - .then( - () => assert_promise_rejects_with_message( - descriptor.CALLS([readValue()]), - new DOMException( - 'GATT Service no longer exists.', 'InvalidStateError'), - 'Service got removed.')); - }); + .then(() => requestDeviceWithKeyDown({ + filters: [{services: ['health_thermometer']}]})) + .then(device => device.gatt.connect()) + .then(gattServer => gattServer.getPrimaryService('health_thermometer')) + .then(service => service.getCharacteristic('measurement_interval')) + .then(characteristic => characteristic.getDescriptor(user_description.name)) + .then(descriptor => { + return setBluetoothFakeAdapter('MissingServiceHeartRateAdapter') + .then(() => assert_promise_rejects_with_message( + descriptor.CALLS([readValue()|writeValue(val)]), + new DOMException( + 'GATT Service no longer exists.', + 'InvalidStateError'), + 'Service got removed.')); + }); }, 'Service gets removed. Reject with InvalidStateError.');
diff --git a/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-position-valid-after-insertion.html b/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-position-valid-after-insertion.html deleted file mode 100644 index 194c845b..0000000 --- a/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-position-valid-after-insertion.html +++ /dev/null
@@ -1,69 +0,0 @@ -<!DOCTYPE html> -<script src="../../../resources/testharness.js"></script> -<script src="../../../resources/testharnessreport.js"></script> -<style> -body { - margin: 0; -} - -.scroller { - height: 100px; - width: 200px; - overflow: scroll; -} - -.padding { - width: 400px; - height: 500px; -} - -.sticky { - width: 25px; - height: 25px; - position: sticky; - top: 20px; - left: 50px; -} -</style> - -<div class="scroller" id="scroller"> - <div class="padding" id="padding"></div> -</div> - -<div class="scroller" id="scroller2"> - <div class="padding" id="padding2"></div> -</div> - -<script> -if (window.internals) { - internals.settings.setCSSStickyPositionEnabled(true); -} - -test(function() { - var scroller = document.getElementById('scroller'); - scroller.scrollTop = 100; - scroller.scrollLeft = 50; - - var sticky = document.createElement('div'); - sticky.className = 'sticky'; - scroller.insertBefore(sticky, document.getElementById('padding')); - - assert_equals(sticky.offsetTop, scroller.scrollTop + 20); - assert_equals(sticky.offsetLeft, scroller.scrollLeft + 50); -}, "offsetTop/offsetLeft should be correct for sticky after insertion"); - -test(function() { - var scroller = document.getElementById('scroller2'); - scroller.scrollTop = 100; - scroller.scrollLeft = 50; - - var sticky = document.createElement('div'); - sticky.className = 'sticky'; - scroller.insertBefore(sticky, document.getElementById('padding2')); - - assert_equals(sticky.getBoundingClientRect().top, 120); - assert_equals(sticky.getBoundingClientRect().left, 50); -}, "getBoundingClientRect should be correct for sticky after insertion"); - - -</script>
diff --git a/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-position-valid-after-layout.html b/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-position-valid-after-layout.html deleted file mode 100644 index bac326d..0000000 --- a/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-position-valid-after-layout.html +++ /dev/null
@@ -1,58 +0,0 @@ -<!DOCTYPE html> -<script src="../../../resources/testharness.js"></script> -<script src="../../../resources/testharnessreport.js"></script> -<style> -body { - margin: 0; -} - -#scroller { - height: 100px; - width: 200px; - overflow: scroll; -} - -.padding { - width: 400px; - height: 500px; -} - -#sticky { - width: 25px; - height: 25px; - position: sticky; - top: 20px; - left: 50px; -} -</style> - -<div id="scroller"> - <div id="sticky"></div> - <div class="padding"></div> -</div> - -<script> -if (window.internals) { - internals.settings.setCSSStickyPositionEnabled(true); -} - -test(function() { - var scroller = document.getElementById('scroller'); - var sticky = document.getElementById('sticky'); - scroller.scrollTop = 100; - scroller.scrollLeft = 50; - scroller.append(document.createElement('div')); - assert_equals(sticky.getBoundingClientRect().top, 20); - assert_equals(sticky.getBoundingClientRect().left, 50); -}, "getBoundingClientRect should be correct for sticky after script-caused layout"); - -test(function() { - var scroller = document.getElementById('scroller'); - var sticky = document.getElementById('sticky'); - scroller.scrollTop = 100; - scroller.scrollLeft = 50; - scroller.append(document.createElement('div')); - assert_equals(sticky.offsetTop, 120); - assert_equals(sticky.offsetLeft, 100); -}, "offsetTop/offsetLeft should be correct for sticky after script-caused layout"); -</script>
diff --git a/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-position-works-with-scroll-apis.html b/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-position-works-with-scroll-apis.html deleted file mode 100644 index d06245c9..0000000 --- a/third_party/WebKit/LayoutTests/fast/css/sticky/sticky-position-works-with-scroll-apis.html +++ /dev/null
@@ -1,126 +0,0 @@ -<!DOCTYPE html> -<script src="../../../resources/testharness.js"></script> -<script src="../../../resources/testharnessreport.js"></script> -<style> -body { - margin: 0; -} - -#scroller { - height: 100px; - width: 200px; - overflow-y: scroll; -} - -.paddingBefore { - height: 150px; -} - -#sticky { - height: 50px; - position: sticky; - top: 20px; -} - -.paddingAfter { - height: 500px; -} -</style> - -<div id="scroller"> - <div class="paddingBefore"></div> - <div id="writer"></div> - <div id="sticky"></div> - <div class="paddingAfter"></div> -</div> - -<script> -if (window.internals) { - internals.settings.setCSSStickyPositionEnabled(true); -} - -// These tests currently mimic the behavior of Firefox for the interaction -// between scrollIntoView() and position:sticky, where the offset location of -// the sticky element is used to determine how far to scroll. This means that -// scrollIntoView() may scroll even when the sticky is already 'in view', and -// attempts to scroll so that the offset position of the sticky is at the top -// of the screen. -// -// TODO(smcgruer): Update tests once http://crbug.com/664246 is resolved. - -test(function() { - var scroller = document.getElementById('scroller'); - var sticky = document.getElementById('sticky'); - var writer = document.getElementById('writer'); - - // Clean the writer. - writer.innerHTML = ''; - - // With no scroll, the sticky element is outside the scroller viewport. - scroller.scrollTop = 0; - - // Deliberately dirty layout to make sure that scrollIntoView() still works. - writer.innerHTML = '<div style="height: 50px;"></div>'; - - sticky.scrollIntoView(); - assert_equals(scroller.scrollTop, 200); -}, "scrollIntoView should scroll when sticky is not visible"); - -test(function() { - var scroller = document.getElementById('scroller'); - var sticky = document.getElementById('sticky'); - var writer = document.getElementById('writer'); - - // Clean the writer. - writer.innerHTML = ''; - - // Scroll so that the sticky element is past the top of the scroller - // viewport, and is thus sticking. - scroller.scrollTop = 200; - - // Deliberately dirty layout to make sure that scrollIntoView() still works. - writer.innerHTML = '<div style="height: 10px;"></div>'; - - // See comment above tests for why this shifts by an additional 20 pixels. - sticky.scrollIntoView(); - assert_equals(scroller.scrollTop, 230); -}, "scrollIntoView should scroll when sticky is already in view"); - -test(function() { - var scroller = document.getElementById('scroller'); - var sticky = document.getElementById('sticky'); - var writer = document.getElementById('writer'); - - // Clean the writer. - writer.innerHTML = ''; - - // With no scroll, the sticky element is outside the scroller viewport. - scroller.scrollTop = 0; - - // Deliberately dirty layout to make sure that scrollIntoViewIfNeeded() - // still works. - writer.innerHTML = '<div style="height: 70px;"></div>'; - - sticky.scrollIntoViewIfNeeded(); - assert_equals(scroller.scrollTop, 195); -}, "scrollIntoViewIfNeeded should scroll when sticky is not visible"); - -test(function() { - var scroller = document.getElementById('scroller'); - var sticky = document.getElementById('sticky'); - var writer = document.getElementById('writer'); - - // Clean the writer. - writer.innerHTML = ''; - - // Scroll so that the sticky element is at the top of the scroller viewport. - scroller.scrollTop = 150; - - // Deliberately dirty layout to make sure that scrollIntoViewIfNeeded() - // still works. - writer.innerHTML = '<div style="height: 20px;"></div>'; - - sticky.scrollIntoViewIfNeeded(); - assert_equals(scroller.scrollTop, 170); -}, "scrollIntoViewIfNeeded should not scroll when sticky is already in view"); -</script>
diff --git a/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/biquad-automation-expected.txt b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/biquad-automation-expected.txt deleted file mode 100644 index 99087ff0..0000000 --- a/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/biquad-automation-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -Test Automation of Biquad Filters - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - - -PASS Output of bandpass filter with frequency automation equals [0,0.27211377024650574,0.17078085243701935,-0.47929149866104126,-0.27997663617134094,0.3924965262413025,0.10922128707170486,-0.3936297297477722,0.0668390765786171,0.40758851170539856,-0.18572545051574707,-0.35690367221832275,0.28689950704574585,0.26041892170906067,-0.3702554702758789,-0.14302822947502136,...] with an element-wise tolerance of 0.0000048429. -PASS Output of bandpass filter with Q automation equals [0,0.013992002233862877,0.052294112741947174,0.1082303449511528,0.17509238421916962,0.24637210369110107,0.3159724175930023,0.3783925771713257,0.4288841784000397,0.4635751247406006,0.47955939173698425,0.47495153546333313,0.4489057660102844,0.40160006284713745,0.3341873586177826,0.2487161010503769,...] with an element-wise tolerance of 0.0000011062. -PASS Output of lowshelf filter with gain automation equals [0,0.47850650548934937,1.554081916809082,3.0527422428131104,4.671957969665527,6.188648223876953,7.4877095222473145,8.524102210998535,9.282732963562012,9.756352424621582,9.939204216003418,9.828425407409668,9.427144050598145,8.746537208557129,7.806419372558594,6.634762763977051,...] with an element-wise tolerance of 0.000014306. -PASS Output of bandpass filter with detune automation equals [0,0.0008340422064065933,0.0014052728656679392,0.0003835858660750091,0.0001248704647878185,0.0012254818575456738,0.0011344455415382981,0.000052847364713670686,0.0004774949047714472,0.0014240697491914034,0.0006955951685085893,-0.000031629722798243165,0.0009216234902851284,0.0013469421537593007,0.0002514156512916088,0.0001623158750589937,...] with an element-wise tolerance of 0.000029535. -PASS Output of peaking filter with automation of all parameters equals [0,0.9876883625984192,-0.30901700258255005,-0.8910065293312073,0.5877852439880371,0.7071067690849304,-0.80901700258255,-0.45399048924446106,0.9510565400123596,0.15643446147441864,-1,0.15643446147441864,0.9510565400123596,-0.45399048924446106,-0.80901700258255,0.7071067690849304,...] with an element-wise tolerance of 0.00062907. -PASS Output of bandpass filter with sinusoidal modulation of bandpass center frequency equals [0,0.0018003738950937986,0.00716581242159009,0.015862563624978065,0.027496544644236565,0.04151911661028862,0.05723972246050835,0.07384545356035233,0.09042731672525406,0.10601259768009186,0.11960244923830032,0.13021349906921387,0.13692189753055573,0.13890819251537323,0.13550083339214325,0.12621651589870453,...] with an element-wise tolerance of 0.000039787. -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/biquad-automation.html b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/biquad-automation.html index 15a0a93..06476e6 100644 --- a/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/biquad-automation.html +++ b/third_party/WebKit/LayoutTests/webaudio/BiquadFilter/biquad-automation.html
@@ -2,7 +2,8 @@ <html> <head> <title>Biquad Automation Test</title> - <script src="../../resources/js-test.js"></script> + <script src="../../resources/testharness.js"></script> + <script src="../../resources/testharnessreport.js"></script> <script src="../resources/audit-util.js"></script> <script src="../resources/audio-testing.js"></script> <script src="../resources/biquad-filters.js"></script> @@ -10,9 +11,7 @@ </head> <body> <script> - description("Test Automation of Biquad Filters"); - window.jsTestIsAsync = true; // Don't need to run these tests at high sampling rate, so just use a low one to reduce memory // usage and complexity. @@ -363,7 +362,6 @@ // All done! audit.defineTask("finish", function (done) { - finishJSTest(); done(); });
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp index ff3aeb0..7e63fa9 100644 --- a/third_party/WebKit/Source/core/dom/Element.cpp +++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -429,7 +429,7 @@ } void Element::scrollIntoView(bool alignToTop) { - ensureCompositingInputsClean(); + document().updateStyleAndLayoutIgnorePendingStylesheetsForNode(this); if (!layoutObject()) return; @@ -454,7 +454,7 @@ } void Element::scrollIntoViewIfNeeded(bool centerIfNeeded) { - ensureCompositingInputsClean(); + document().updateStyleAndLayoutIgnorePendingStylesheetsForNode(this); if (!layoutObject()) return; @@ -634,7 +634,7 @@ } int Element::offsetLeft() { - ensureCompositingInputsClean(); + document().updateStyleAndLayoutIgnorePendingStylesheetsForNode(this); if (LayoutBoxModelObject* layoutObject = layoutBoxModelObject()) return adjustLayoutUnitForAbsoluteZoom( LayoutUnit(layoutObject->pixelSnappedOffsetLeft(offsetParent())), @@ -644,7 +644,7 @@ } int Element::offsetTop() { - ensureCompositingInputsClean(); + document().updateStyleAndLayoutIgnorePendingStylesheetsForNode(this); if (LayoutBoxModelObject* layoutObject = layoutBoxModelObject()) return adjustLayoutUnitForAbsoluteZoom( LayoutUnit(layoutObject->pixelSnappedOffsetTop(offsetParent())), @@ -1119,7 +1119,7 @@ } void Element::clientQuads(Vector<FloatQuad>& quads) { - ensureCompositingInputsClean(); + document().updateStyleAndLayoutIgnorePendingStylesheetsForNode(this); LayoutObject* elementLayoutObject = layoutObject(); if (!elementLayoutObject) @@ -4120,19 +4120,6 @@ activityLogger->logEvent("blinkSetAttribute", argv.size(), argv.data()); } -void Element::ensureCompositingInputsClean() { - if (!inActiveDocument()) - return; - - // The call to updateLifecycleToCompositingCleanPlusScrolling| below would - // also run layout for us if we omitted this call. However we do not want to - // include pending style sheets when doing the layout, hence this call. - document().updateStyleAndLayoutIgnorePendingStylesheets(); - - if (FrameView* view = document().view()) - view->updateLifecycleToCompositingCleanPlusScrolling(); -} - DEFINE_TRACE(Element) { if (hasRareData()) visitor->trace(elementRareData());
diff --git a/third_party/WebKit/Source/core/dom/Element.h b/third_party/WebKit/Source/core/dom/Element.h index aa1466f..8a26e38 100644 --- a/third_party/WebKit/Source/core/dom/Element.h +++ b/third_party/WebKit/Source/core/dom/Element.h
@@ -801,11 +801,6 @@ virtual void parserDidSetAttributes() {} - // Helper method which ensures that compositing inputs have been cleaned. - // Cleaning the compositing inputs is required when computing the location of - // position:sticky elements or their descendants. - void ensureCompositingInputsClean(); - private: void scrollLayoutBoxBy(const ScrollToOptions&); void scrollLayoutBoxTo(const ScrollToOptions&);
diff --git a/third_party/WebKit/Source/core/dom/ElementTest.cpp b/third_party/WebKit/Source/core/dom/ElementTest.cpp index 40de9e4c..30064c6 100644 --- a/third_party/WebKit/Source/core/dom/ElementTest.cpp +++ b/third_party/WebKit/Source/core/dom/ElementTest.cpp
@@ -7,8 +7,6 @@ #include "core/dom/Document.h" #include "core/frame/FrameView.h" #include "core/html/HTMLHtmlElement.h" -#include "core/layout/LayoutBoxModelObject.h" -#include "core/paint/PaintLayer.h" #include "core/testing/DummyPageHolder.h" #include "testing/gtest/include/gtest/gtest.h" #include <memory> @@ -25,131 +23,4 @@ << "<html> with designMode=on should be focusable."; } -// Verifies that calling getBoundingClientRect cleans compositor inputs. -// Cleaning the compositor inputs is required so that position:sticky elements -// and their descendants have the correct location. -TEST(ElementTest, GetBoundingClientRectUpdatesCompositorInputs) { - std::unique_ptr<DummyPageHolder> pageHolder = DummyPageHolder::create(); - Document& document = pageHolder->document(); - - document.view()->updateAllLifecyclePhases(); - EXPECT_EQ(DocumentLifecycle::PaintClean, document.lifecycle().state()); - - document.body()->setInnerHTML("<div id='test'></div>"); - EXPECT_EQ(DocumentLifecycle::VisualUpdatePending, - document.lifecycle().state()); - - document.body()->getBoundingClientRect(); - EXPECT_EQ(DocumentLifecycle::CompositingClean, document.lifecycle().state()); -} - -// Verifies that calling scrollIntoView* cleans compositor inputs. Cleaning the -// compositor inputs is required so that position:sticky elements and their -// descendants have the correct location. -TEST(ElementTest, ScrollIntoViewUpdatesCompositorInputs) { - std::unique_ptr<DummyPageHolder> pageHolder = DummyPageHolder::create(); - Document& document = pageHolder->document(); - - document.view()->updateAllLifecyclePhases(); - EXPECT_EQ(DocumentLifecycle::PaintClean, document.lifecycle().state()); - - document.body()->setInnerHTML("<div id='test'></div>"); - EXPECT_EQ(DocumentLifecycle::VisualUpdatePending, - document.lifecycle().state()); - - document.body()->scrollIntoView(); - EXPECT_EQ(DocumentLifecycle::CompositingClean, document.lifecycle().state()); - - document.body()->setInnerHTML("<div id='test2'></div>"); - EXPECT_EQ(DocumentLifecycle::VisualUpdatePending, - document.lifecycle().state()); - - document.body()->scrollIntoViewIfNeeded(); - EXPECT_EQ(DocumentLifecycle::CompositingClean, document.lifecycle().state()); -} - -// Verifies that calling offsetTop/offsetLeft cleans compositor inputs. -// Cleaning the compositor inputs is required so that position:sticky elements -// and their descendants have the correct location. -TEST(ElementTest, OffsetTopAndLeftUpdateCompositorInputs) { - std::unique_ptr<DummyPageHolder> pageHolder = DummyPageHolder::create(); - Document& document = pageHolder->document(); - - document.view()->updateAllLifecyclePhases(); - EXPECT_EQ(DocumentLifecycle::PaintClean, document.lifecycle().state()); - - document.body()->setInnerHTML("<div id='test'></div>"); - EXPECT_EQ(DocumentLifecycle::VisualUpdatePending, - document.lifecycle().state()); - - document.body()->offsetTop(); - EXPECT_EQ(DocumentLifecycle::CompositingClean, document.lifecycle().state()); - - document.body()->setInnerHTML("<div id='test2'></div>"); - EXPECT_EQ(DocumentLifecycle::VisualUpdatePending, - document.lifecycle().state()); - - document.body()->offsetLeft(); - EXPECT_EQ(DocumentLifecycle::CompositingClean, document.lifecycle().state()); -} - -TEST(ElementTest, OffsetTopAndLeftCorrectForStickyElementsAfterInsertion) { - std::unique_ptr<DummyPageHolder> pageHolder = DummyPageHolder::create(); - Document& document = pageHolder->document(); - - document.body()->setInnerHTML( - "<style>body { margin: 0 }" - "#scroller { overflow: scroll; height: 100px; width: 100px; }" - "#sticky { height: 25px; position: sticky; top: 0; left: 25px; }" - "#padding { height: 500px; width: 300px; }</style>" - "<div id='scroller'><div id='writer'></div><div id='sticky'></div>" - "<div id='padding'></div></div>"); - document.view()->updateAllLifecyclePhases(); - - Element* scroller = document.getElementById("scroller"); - Element* writer = document.getElementById("writer"); - Element* sticky = document.getElementById("sticky"); - - ASSERT_TRUE(scroller); - ASSERT_TRUE(writer); - ASSERT_TRUE(sticky); - - scroller->scrollTo(0, 200.0); - - // After scrolling, the position:sticky element should be offset to stay at - // the top of the viewport. - EXPECT_EQ(scroller->scrollTop(), sticky->offsetTop()); - - // Insert a new <div> above the sticky. This will dirty layout. - writer->setInnerHTML("<div style='height: 100px;'></div>"); - EXPECT_EQ(DocumentLifecycle::VisualUpdatePending, - document.lifecycle().state()); - - // Querying the new offset of the sticky element should now cause both layout - // and compositing inputs to be clean and should return the correct offset. - int offsetTop = sticky->offsetTop(); - EXPECT_EQ(DocumentLifecycle::CompositingClean, document.lifecycle().state()); - EXPECT_FALSE( - sticky->layoutBoxModelObject()->layer()->needsCompositingInputsUpdate()); - EXPECT_EQ(scroller->scrollTop(), offsetTop); - - scroller->scrollTo(50.0, 0); - - // After scrolling, the position:sticky element should be offset to stay 25 - // pixels from the left of the viewport. - EXPECT_EQ(scroller->scrollLeft() + 25, sticky->offsetLeft()); - - // Insert a new <div> above the sticky. This will dirty layout. - writer->setInnerHTML("<div style='width: 700px;'></div>"); - EXPECT_EQ(DocumentLifecycle::VisualUpdatePending, - document.lifecycle().state()); - - // Again getting the offset should cause layout and compositing to be clean. - int offsetLeft = sticky->offsetLeft(); - EXPECT_EQ(DocumentLifecycle::CompositingClean, document.lifecycle().state()); - EXPECT_FALSE( - sticky->layoutBoxModelObject()->layer()->needsCompositingInputsUpdate()); - EXPECT_EQ(scroller->scrollLeft() + 25, offsetLeft); -} - } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/HTMLElement.cpp b/third_party/WebKit/Source/core/html/HTMLElement.cpp index 1ca5128c..deaffb10 100644 --- a/third_party/WebKit/Source/core/html/HTMLElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLElement.cpp
@@ -1161,7 +1161,6 @@ } int HTMLElement::offsetLeftForBinding() { - ensureCompositingInputsClean(); Element* offsetParent = unclosedOffsetParent(); if (LayoutBoxModelObject* layoutObject = layoutBoxModelObject()) return adjustLayoutUnitForAbsoluteZoom( @@ -1172,7 +1171,6 @@ } int HTMLElement::offsetTopForBinding() { - ensureCompositingInputsClean(); Element* offsetParent = unclosedOffsetParent(); if (LayoutBoxModelObject* layoutObject = layoutBoxModelObject()) return adjustLayoutUnitForAbsoluteZoom(
diff --git a/third_party/WebKit/Source/core/layout/LayoutCounter.cpp b/third_party/WebKit/Source/core/layout/LayoutCounter.cpp index c3319605..2213a17 100644 --- a/third_party/WebKit/Source/core/layout/LayoutCounter.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutCounter.cpp
@@ -426,7 +426,7 @@ } LayoutCounter::LayoutCounter(Document* node, const CounterContent& counter) - : LayoutText(node, StringImpl::empty()), + : LayoutText(node, StringImpl::empty), m_counter(counter), m_counterNode(nullptr), m_nextForSameCounter(nullptr) {
diff --git a/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp b/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp index e6f24dd..05cace5f 100644 --- a/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp
@@ -70,7 +70,7 @@ ASSERT(!firstChild()); m_innerBlock = createAnonymousBlock(); - m_buttonText = new LayoutText(&document(), StringImpl::empty()); + m_buttonText = new LayoutText(&document(), StringImpl::empty); // We need to set the text explicitly though it was specified in the // constructor because LayoutText doesn't refer to the text // specified in the constructor in a case of re-transforming.
diff --git a/third_party/WebKit/Source/core/layout/LayoutWordBreak.cpp b/third_party/WebKit/Source/core/layout/LayoutWordBreak.cpp index 64c2c08..574b164 100644 --- a/third_party/WebKit/Source/core/layout/LayoutWordBreak.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutWordBreak.cpp
@@ -31,7 +31,7 @@ namespace blink { LayoutWordBreak::LayoutWordBreak(HTMLElement* element) - : LayoutText(element, StringImpl::empty()) {} + : LayoutText(element, StringImpl::empty) {} bool LayoutWordBreak::isWordBreak() const { return true;
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp index 96d92ae..8e915fe 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
@@ -829,10 +829,6 @@ DisableCompositingQueryAsserts disabler; positionOverflowControls(); - - // Layout of a scrollable area, or any of its descendants (sticky or - // otherwise), invalidates the cached sticky constraints. - invalidateAllStickyConstraints(); } void PaintLayerScrollableArea::clampScrollOffsetAfterOverflowChange() {
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp index c633a7f..d0cb1b8 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableAreaTest.cpp
@@ -28,7 +28,7 @@ } }; -} // namespace +} // namespace { class PaintLayerScrollableAreaTest : public RenderingTest { public: @@ -548,31 +548,4 @@ .Times(0); scrollableArea->setScrollOffset(ScrollOffset(2, 2), ProgrammaticScroll); } - -TEST_F(PaintLayerScrollableAreaTest, - StickyPositionConstraintsInvalidatedByLayout) { - setBodyInnerHTML( - "<style>#scroller { overflow-y: scroll; height: 100px; }" - "#sticky { height: 25px; position: sticky; top: 0; }" - "#padding { height: 500px; }</style>" - "<div id='scroller'><div id='sticky'></div><div id='padding'></div>" - "</div>"); - - LayoutBoxModelObject* scroller = - toLayoutBoxModelObject(getLayoutObjectByElementId("scroller")); - LayoutBoxModelObject* sticky = - toLayoutBoxModelObject(getLayoutObjectByElementId("sticky")); - - EXPECT_FALSE(sticky->layer()->needsCompositingInputsUpdate()); - - PaintLayerScrollableArea* scrollableArea = scroller->getScrollableArea(); - ASSERT_TRUE(scrollableArea); - - // Fake layout. - scrollableArea->updateAfterLayout(); - - EXPECT_TRUE(sticky->layer()->needsCompositingInputsUpdate()); - EXPECT_EQ(0u, scrollableArea->stickyConstraintsMap().size()); } - -} // namespace blink
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.cpp index 8b0ca46..9bb73d6 100644 --- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.cpp +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.cpp
@@ -7,7 +7,6 @@ #include "bindings/core/v8/ScriptPromise.h" #include "bindings/core/v8/ScriptPromiseResolver.h" #include "core/dom/DOMException.h" -#include "modules/bluetooth/Bluetooth.h" #include "modules/bluetooth/BluetoothError.h" #include "modules/bluetooth/BluetoothRemoteGATTService.h" #include "modules/bluetooth/BluetoothRemoteGATTUtils.h" @@ -74,10 +73,7 @@ ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); ScriptPromise promise = resolver->promise(); getGatt()->AddToActiveAlgorithms(resolver); - - mojom::blink::WebBluetoothService* service = - m_characteristic->m_device->bluetooth()->service(); - service->RemoteDescriptorReadValue( + getService()->RemoteDescriptorReadValue( m_descriptor->instance_id, convertToBaseCallback( WTF::bind(&BluetoothRemoteGATTDescriptor::ReadValueCallback, @@ -86,15 +82,73 @@ return promise; } +void BluetoothRemoteGATTDescriptor::WriteValueCallback( + ScriptPromiseResolver* resolver, + const Vector<uint8_t>& value, + mojom::blink::WebBluetoothResult result) { + if (!resolver->getExecutionContext() || + resolver->getExecutionContext()->isContextDestroyed()) + return; + + // If the resolver is not in the set of ActiveAlgorithms then the frame + // disconnected so we reject. + if (!getGatt()->RemoveFromActiveAlgorithms(resolver)) { + resolver->reject(BluetoothRemoteGATTUtils::CreateDOMException( + BluetoothRemoteGATTUtils::ExceptionType::kGATTServerDisconnected)); + return; + } + + if (result == mojom::blink::WebBluetoothResult::SUCCESS) { + m_value = BluetoothRemoteGATTUtils::ConvertWTFVectorToDataView(value); + resolver->resolve(); + } else { + resolver->reject(BluetoothError::take(resolver, result)); + } +} + ScriptPromise BluetoothRemoteGATTDescriptor::writeValue( ScriptState* scriptState, const DOMArrayPiece& value) { - // TODO(668838): Implement WebBluetooth descriptor.writeValue() - return ScriptPromise::rejectWithDOMException( - scriptState, - DOMException::create(NotSupportedError, - "descriptor writeValue is not implemented " - "yet. See https://goo.gl/J6ASzs")); + if (!getGatt()->connected()) { + return ScriptPromise::rejectWithDOMException( + scriptState, + BluetoothRemoteGATTUtils::CreateDOMException( + BluetoothRemoteGATTUtils::ExceptionType::kGATTServerNotConnected)); + } + + if (!getGatt()->device()->isValidDescriptor(m_descriptor->instance_id)) { + return ScriptPromise::rejectWithDOMException( + scriptState, + BluetoothRemoteGATTUtils::CreateDOMException( + BluetoothRemoteGATTUtils::ExceptionType::kInvalidDescriptor)); + } + + // Partial implementation of writeValue algorithm: + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue + + // If bytes is more than 512 bytes long (the maximum length of an attribute + // value, per Long Attribute Values) return a promise rejected with an + // InvalidModificationError and abort. + if (value.byteLength() > 512) { + return ScriptPromise::rejectWithDOMException( + scriptState, DOMException::create(InvalidModificationError, + "Value can't exceed 512 bytes.")); + } + + // Let valueVector be a copy of the bytes held by value. + Vector<uint8_t> valueVector; + valueVector.append(value.bytes(), value.byteLength()); + + ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); + ScriptPromise promise = resolver->promise(); + getGatt()->AddToActiveAlgorithms(resolver); + getService()->RemoteDescriptorWriteValue( + m_descriptor->instance_id, valueVector, + convertToBaseCallback(WTF::bind( + &BluetoothRemoteGATTDescriptor::WriteValueCallback, + wrapPersistent(this), wrapPersistent(resolver), valueVector))); + + return promise; } DEFINE_TRACE(BluetoothRemoteGATTDescriptor) {
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.h b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.h index b491c1d..175db616 100644 --- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.h +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTDescriptor.h
@@ -9,6 +9,7 @@ #include "core/dom/DOMArrayPiece.h" #include "core/dom/DOMDataView.h" #include "modules/EventTargetModules.h" +#include "modules/bluetooth/Bluetooth.h" #include "modules/bluetooth/BluetoothRemoteGATTCharacteristic.h" #include "modules/bluetooth/BluetoothRemoteGATTService.h" #include "platform/heap/Handle.h" @@ -54,11 +55,18 @@ friend class DescriptorReadValueCallback; BluetoothRemoteGATTServer* getGatt() { return m_characteristic->getGatt(); } + mojom::blink::WebBluetoothService* getService() { + return m_characteristic->m_device->bluetooth()->service(); + } void ReadValueCallback(ScriptPromiseResolver*, mojom::blink::WebBluetoothResult, const Optional<Vector<uint8_t>>&); + void WriteValueCallback(ScriptPromiseResolver*, + const Vector<uint8_t>&, + mojom::blink::WebBluetoothResult); + mojom::blink::WebBluetoothRemoteGATTDescriptorPtr m_descriptor; Member<BluetoothRemoteGATTCharacteristic> m_characteristic; Member<DOMDataView> m_value;
diff --git a/third_party/WebKit/Source/modules/vr/NavigatorVR.cpp b/third_party/WebKit/Source/modules/vr/NavigatorVR.cpp index c29f840..076b64f 100644 --- a/third_party/WebKit/Source/modules/vr/NavigatorVR.cpp +++ b/third_party/WebKit/Source/modules/vr/NavigatorVR.cpp
@@ -9,6 +9,7 @@ #include "core/dom/Document.h" #include "core/dom/DocumentUserGestureToken.h" #include "core/dom/ExceptionCode.h" +#include "core/dom/Fullscreen.h" #include "core/frame/LocalDOMWindow.h" #include "core/frame/LocalFrame.h" #include "core/frame/Navigator.h" @@ -132,7 +133,11 @@ void NavigatorVR::didAddEventListener(LocalDOMWindow* window, const AtomicString& eventType) { - if (eventType == EventTypeNames::vrdisplayactivate) { + // TODO(mthiesse): Remove fullscreen requirement for presentation. See + // crbug.com/687369 + if (eventType == EventTypeNames::vrdisplayactivate && + supplementable()->frame() && supplementable()->frame()->document() && + Fullscreen::fullscreenEnabled(*supplementable()->frame()->document())) { controller()->setListeningForActivate(true); m_listeningForActivate = true; } else if (eventType == EventTypeNames::vrdisplayconnect) {
diff --git a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp index 6be80f1..4810e4f 100644 --- a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp +++ b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
@@ -238,6 +238,17 @@ return promise; } + // TODO(mthiesse): Remove fullscreen requirement for presentation. See + // crbug.com/687369 + Document* doc = this->document(); + if (!doc || !Fullscreen::fullscreenEnabled(*doc)) { + DOMException* exception = + DOMException::create(InvalidStateError, "Fullscreen is not enabled."); + resolver->reject(exception); + ReportPresentationResult(PresentationResult::FullscreenNotEnabled); + return promise; + } + // A valid number of layers must be provided in order to present. if (layers.size() == 0 || layers.size() > m_capabilities->maxLayers()) { forceExitPresent();
diff --git a/third_party/WebKit/Source/modules/vr/VRDisplay.h b/third_party/WebKit/Source/modules/vr/VRDisplay.h index c756314..7a3d101 100644 --- a/third_party/WebKit/Source/modules/vr/VRDisplay.h +++ b/third_party/WebKit/Source/modules/vr/VRDisplay.h
@@ -192,6 +192,7 @@ InvalidLayerBounds = 10, ServiceInactive = 11, RequestDenied = 12, + FullscreenNotEnabled = 13, PresentationResultMax, // Must be last member of enum. };
diff --git a/third_party/WebKit/Source/platform/weborigin/KURL.cpp b/third_party/WebKit/Source/platform/weborigin/KURL.cpp index f34a5bc..6df46cf 100644 --- a/third_party/WebKit/Source/platform/weborigin/KURL.cpp +++ b/third_party/WebKit/Source/platform/weborigin/KURL.cpp
@@ -836,7 +836,7 @@ } StringView KURL::stringViewForInvalidComponent() const { - return m_string.isNull() ? StringView() : StringView(StringImpl::empty()); + return m_string.isNull() ? StringView() : StringView(StringImpl::empty); } StringView KURL::componentStringView(const url::Component& component) const {
diff --git a/third_party/WebKit/Source/wtf/ThreadingPthreads.cpp b/third_party/WebKit/Source/wtf/ThreadingPthreads.cpp index 886e661..6120cb6 100644 --- a/third_party/WebKit/Source/wtf/ThreadingPthreads.cpp +++ b/third_party/WebKit/Source/wtf/ThreadingPthreads.cpp
@@ -81,10 +81,6 @@ // This should only be called once. DCHECK(!atomicallyInitializedStaticMutex); - // StringImpl::empty() does not construct its static string in a threadsafe - // fashion, so ensure it has been initialized from here. - StringImpl::empty(); - StringImpl::empty16Bit(); atomicallyInitializedStaticMutex = new Mutex; wtfThreadData(); initializeDates();
diff --git a/third_party/WebKit/Source/wtf/ThreadingWin.cpp b/third_party/WebKit/Source/wtf/ThreadingWin.cpp index 8808450..3c21d2a 100644 --- a/third_party/WebKit/Source/wtf/ThreadingWin.cpp +++ b/third_party/WebKit/Source/wtf/ThreadingWin.cpp
@@ -148,10 +148,6 @@ // This should only be called once. DCHECK(!atomicallyInitializedStaticMutex); - // StringImpl::empty() does not construct its static string in a threadsafe - // fashion, so ensure it has been initialized from here. - StringImpl::empty(); - StringImpl::empty16Bit(); atomicallyInitializedStaticMutex = new Mutex; wtfThreadData(); initializeDates();
diff --git a/third_party/WebKit/Source/wtf/text/AtomicStringTable.cpp b/third_party/WebKit/Source/wtf/text/AtomicStringTable.cpp index 7ca6f715..bc40b4d 100644 --- a/third_party/WebKit/Source/wtf/text/AtomicStringTable.cpp +++ b/third_party/WebKit/Source/wtf/text/AtomicStringTable.cpp
@@ -148,7 +148,7 @@ return nullptr; if (!length) - return StringImpl::empty(); + return StringImpl::empty; UCharBuffer buffer = {s, length}; return addToStringTable<UCharBuffer, UCharBufferTranslator>(buffer); @@ -178,7 +178,7 @@ return nullptr; if (!length) - return StringImpl::empty(); + return StringImpl::empty; LCharBuffer buffer = {s, length}; return addToStringTable<LCharBuffer, LCharBufferTranslator>(buffer); @@ -186,7 +186,7 @@ StringImpl* AtomicStringTable::add(StringImpl* string) { if (!string->length()) - return StringImpl::empty(); + return StringImpl::empty; StringImpl* result = *m_table.insert(string).storedValue;
diff --git a/third_party/WebKit/Source/wtf/text/StringImpl.cpp b/third_party/WebKit/Source/wtf/text/StringImpl.cpp index 6654e30..c784115 100644 --- a/third_party/WebKit/Source/wtf/text/StringImpl.cpp +++ b/third_party/WebKit/Source/wtf/text/StringImpl.cpp
@@ -28,6 +28,7 @@ #include "wtf/DynamicAnnotations.h" #include "wtf/LeakAnnotations.h" #include "wtf/PtrUtil.h" +#include "wtf/StaticConstructors.h" #include "wtf/StdLibExtras.h" #include "wtf/allocator/Partitions.h" #include "wtf/text/AtomicString.h" @@ -344,7 +345,7 @@ LChar*& data) { if (!length) { data = 0; - return empty(); + return empty; } // Allocate a single buffer large enough to contain the StringImpl @@ -361,7 +362,7 @@ UChar*& data) { if (!length) { data = 0; - return empty(); + return empty; } // Allocate a single buffer large enough to contain the StringImpl @@ -397,6 +398,22 @@ unsigned StringImpl::m_highestStaticStringLength = 0; +DEFINE_GLOBAL(StringImpl, globalEmpty); +DEFINE_GLOBAL(StringImpl, globalEmpty16Bit); +// Callers need the global empty strings to be non-const. +StringImpl* StringImpl::empty = const_cast<StringImpl*>(&globalEmpty); +StringImpl* StringImpl::empty16Bit = const_cast<StringImpl*>(&globalEmpty16Bit); +void StringImpl::initStatics() { + new ((void*)empty) StringImpl(ConstructEmptyString); + new ((void*)empty16Bit) StringImpl(ConstructEmptyString16Bit); + WTF_ANNOTATE_BENIGN_RACE(StringImpl::empty, + "Benign race on the reference counter of a static " + "string created by StringImpl::empty"); + WTF_ANNOTATE_BENIGN_RACE(StringImpl::empty16Bit, + "Benign race on the reference counter of a static " + "string created by StringImpl::empty16Bit"); +} + StringImpl* StringImpl::createStatic(const char* string, unsigned length, unsigned hash) { @@ -451,7 +468,7 @@ PassRefPtr<StringImpl> StringImpl::create(const UChar* characters, unsigned length) { if (!characters || !length) - return empty(); + return empty; UChar* data; RefPtr<StringImpl> string = createUninitialized(length, data); @@ -462,7 +479,7 @@ PassRefPtr<StringImpl> StringImpl::create(const LChar* characters, unsigned length) { if (!characters || !length) - return empty(); + return empty; LChar* data; RefPtr<StringImpl> string = createUninitialized(length, data); @@ -473,7 +490,7 @@ PassRefPtr<StringImpl> StringImpl::create8BitIfPossible(const UChar* characters, unsigned length) { if (!characters || !length) - return empty(); + return empty; LChar* data; RefPtr<StringImpl> string = createUninitialized(length, data); @@ -489,7 +506,7 @@ PassRefPtr<StringImpl> StringImpl::create(const LChar* string) { if (!string) - return empty(); + return empty; size_t length = strlen(reinterpret_cast<const char*>(string)); RELEASE_ASSERT(length <= numeric_limits<unsigned>::max()); return create(string, length); @@ -520,7 +537,7 @@ PassRefPtr<StringImpl> StringImpl::substring(unsigned start, unsigned length) const { if (start >= m_length) - return empty(); + return empty; unsigned maxLength = m_length - start; if (length >= maxLength) { // PassRefPtr has trouble dealing with const arguments. It should be updated @@ -959,7 +976,7 @@ inline PassRefPtr<StringImpl> StringImpl::stripMatchedCharacters( UCharPredicate predicate) { if (!m_length) - return empty(); + return empty; unsigned start = 0; unsigned end = m_length - 1; @@ -971,7 +988,7 @@ // only white space if (start > end) - return empty(); + return empty; // skip white space from end while (end && predicate(is8Bit() ? characters8()[end] : characters16()[end]))
diff --git a/third_party/WebKit/Source/wtf/text/StringImpl.h b/third_party/WebKit/Source/wtf/text/StringImpl.h index 77dfcc3..afdb6af 100644 --- a/third_party/WebKit/Source/wtf/text/StringImpl.h +++ b/third_party/WebKit/Source/wtf/text/StringImpl.h
@@ -205,8 +205,13 @@ m_isStatic(true) {} public: + static StringImpl* empty; + static StringImpl* empty16Bit; + ~StringImpl(); + static void initStatics(); + static StringImpl* createStatic(const char* string, unsigned length, unsigned hash); @@ -324,9 +329,6 @@ destroyIfNotStatic(); } - static StringImpl* empty(); - static StringImpl* empty16Bit(); - // FIXME: Does this really belong in StringImpl? template <typename T> static void copyChars(T* destination,
diff --git a/third_party/WebKit/Source/wtf/text/StringMac.mm b/third_party/WebKit/Source/wtf/text/StringMac.mm index 1311cab..cb410b2 100644 --- a/third_party/WebKit/Source/wtf/text/StringMac.mm +++ b/third_party/WebKit/Source/wtf/text/StringMac.mm
@@ -30,7 +30,7 @@ CFIndex size = CFStringGetLength(reinterpret_cast<CFStringRef>(str)); if (size == 0) - m_impl = StringImpl::empty(); + m_impl = StringImpl::empty; else { Vector<LChar, 1024> lcharBuffer(size); CFIndex usedBufLen;
diff --git a/third_party/WebKit/Source/wtf/text/StringStatics.cpp b/third_party/WebKit/Source/wtf/text/StringStatics.cpp index 2bb0dbe..ff7910a 100644 --- a/third_party/WebKit/Source/wtf/text/StringStatics.cpp +++ b/third_party/WebKit/Source/wtf/text/StringStatics.cpp
@@ -32,22 +32,6 @@ namespace WTF { -StringImpl* StringImpl::empty() { - DEFINE_STATIC_LOCAL(StringImpl, emptyString, (ConstructEmptyString)); - WTF_ANNOTATE_BENIGN_RACE(&emptyString, - "Benign race on the reference counter of a static " - "string created by StringImpl::empty"); - return &emptyString; -} - -StringImpl* StringImpl::empty16Bit() { - DEFINE_STATIC_LOCAL(StringImpl, emptyString, (ConstructEmptyString16Bit)); - WTF_ANNOTATE_BENIGN_RACE(&emptyString, - "Benign race on the reference counter of a static " - "string created by StringImpl::empty16Bit"); - return &emptyString; -} - WTF_EXPORT DEFINE_GLOBAL(AtomicString, nullAtom); WTF_EXPORT DEFINE_GLOBAL(AtomicString, emptyAtom); WTF_EXPORT DEFINE_GLOBAL(AtomicString, starAtom); @@ -89,6 +73,8 @@ void StringStatics::init() { DCHECK(isMainThread()); + StringImpl::initStatics(); + // FIXME: These should be allocated at compile time. new (NotNull, (void*)&starAtom) AtomicString("*"); new (NotNull, (void*)&xmlAtom) AtomicString(addStaticASCIILiteral("xml"));
diff --git a/third_party/WebKit/Source/wtf/text/StringView.h b/third_party/WebKit/Source/wtf/text/StringView.h index ec078f21..bd22113 100644 --- a/third_party/WebKit/Source/wtf/text/StringView.h +++ b/third_party/WebKit/Source/wtf/text/StringView.h
@@ -68,7 +68,7 @@ // From a literal string or LChar buffer: StringView(const LChar* chars, unsigned length) - : m_impl(StringImpl::empty()), m_characters8(chars), m_length(length) {} + : m_impl(StringImpl::empty), m_characters8(chars), m_length(length) {} StringView(const char* chars, unsigned length) : StringView(reinterpret_cast<const LChar*>(chars), length) {} StringView(const LChar* chars) @@ -79,7 +79,7 @@ // From a wide literal string or UChar buffer. StringView(const UChar* chars, unsigned length) - : m_impl(StringImpl::empty16Bit()), + : m_impl(StringImpl::empty16Bit), m_characters16(chars), m_length(length) {} StringView(const UChar* chars); @@ -203,7 +203,7 @@ inline void StringView::clear() { m_length = 0; m_bytes = nullptr; - m_impl = StringImpl::empty(); // mark as 8 bit. + m_impl = StringImpl::empty; // mark as 8 bit. } inline void StringView::set(const StringImpl& impl,
diff --git a/third_party/WebKit/Source/wtf/text/WTFString.cpp b/third_party/WebKit/Source/wtf/text/WTFString.cpp index 22c6d0b..95c4159 100644 --- a/third_party/WebKit/Source/wtf/text/WTFString.cpp +++ b/third_party/WebKit/Source/wtf/text/WTFString.cpp
@@ -251,7 +251,7 @@ m_impl = make16BitFrom8BitSource(m_impl->characters8(), length).releaseImpl(); else - m_impl = StringImpl::empty16Bit(); + m_impl = StringImpl::empty16Bit; } void String::truncate(unsigned length) { @@ -776,12 +776,12 @@ } const String& emptyString() { - DEFINE_STATIC_LOCAL(String, emptyString, (StringImpl::empty())); + DEFINE_STATIC_LOCAL(String, emptyString, (StringImpl::empty)); return emptyString; } const String& emptyString16Bit() { - DEFINE_STATIC_LOCAL(String, emptyString, (StringImpl::empty16Bit())); + DEFINE_STATIC_LOCAL(String, emptyString, (StringImpl::empty16Bit)); return emptyString; }
diff --git a/third_party/WebKit/Source/wtf/text/WTFString.h b/third_party/WebKit/Source/wtf/text/WTFString.h index a6466448..80508ad1 100644 --- a/third_party/WebKit/Source/wtf/text/WTFString.h +++ b/third_party/WebKit/Source/wtf/text/WTFString.h
@@ -104,7 +104,7 @@ template <typename CharType> static String adopt(StringBuffer<CharType>& buffer) { if (!buffer.length()) - return StringImpl::empty(); + return StringImpl::empty; return String(buffer.release()); } @@ -489,7 +489,7 @@ template <size_t inlineCapacity> String::String(const Vector<UChar, inlineCapacity>& vector) : m_impl(vector.size() ? StringImpl::create(vector.data(), vector.size()) - : StringImpl::empty()) {} + : StringImpl::empty) {} template <> inline const LChar* String::getCharacters<LChar>() const {
diff --git a/third_party/WebKit/Source/wtf/text/WTFStringTest.cpp b/third_party/WebKit/Source/wtf/text/WTFStringTest.cpp index 0f6c640..b8adf49 100644 --- a/third_party/WebKit/Source/wtf/text/WTFStringTest.cpp +++ b/third_party/WebKit/Source/wtf/text/WTFStringTest.cpp
@@ -445,14 +445,14 @@ EXPECT_FALSE(string16.is8Bit()); EXPECT_EQ("16bit", string16); - String empty8(StringImpl::empty()); + String empty8(StringImpl::empty); EXPECT_TRUE(empty8.is8Bit()); empty8.ensure16Bit(); EXPECT_FALSE(empty8.is8Bit()); EXPECT_TRUE(empty8.isEmpty()); EXPECT_FALSE(empty8.isNull()); - String empty16(StringImpl::empty16Bit()); + String empty16(StringImpl::empty16Bit); EXPECT_FALSE(empty16.is8Bit()); empty16.ensure16Bit(); EXPECT_FALSE(empty16.is8Bit());
diff --git a/third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom b/third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom index ed1adc8..43ac52f4 100644 --- a/third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom +++ b/third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom
@@ -250,6 +250,14 @@ string descriptor_instance_id) => ( WebBluetoothResult result, array<uint8>? value); + + // Writes a value to the descriptor identified by + // |descriptor_instance_id|. The callback is run with + // WebBluetoothResult::SUCCESS if the value was successfully + // written. + RemoteDescriptorWriteValue( + string descriptor_instance_id, + array<uint8> value) => (WebBluetoothResult result); }; // Classes should implement this interface and pass an associated pointer
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 05ece5a..15be521 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -5069,6 +5069,19 @@ </summary> </histogram> +<histogram name="Bluetooth.Web.Descriptor.WriteValue.Outcome" + enum="WebBluetoothGATTOperationOutcome"> + <owner>jyasskin@chromium.org</owner> + <owner>ortuno@chromium.org</owner> + <owner>scheib@chromium.org</owner> + <summary> + Records the outcome of a call to descriptor.writeValue(). Used to know what + types of errors users are seeing. The results will be used to determine how + common these errors are and if we need to provide better error messages to + the users. + </summary> +</histogram> + <histogram name="Bluetooth.Web.FunctionCall.Count" enum="WebBluetoothFunction"> <owner>jyasskin@chromium.org</owner> <owner>ortuno@chromium.org</owner> @@ -10097,6 +10110,24 @@ </summary> </histogram> +<histogram name="DesktopIOSPromotion.OAuthTokenCompletion" + enum="BooleanSuccess"> + <owner>justincohen@chromium.org</owner> + <summary> + Whether getting the OAuth token was successful for a desktop to ios + promotion query. + </summary> +</histogram> + +<histogram name="DesktopIOSPromotion.OAuthTokenResponseCode" + enum="CombinedHttpResponseAndNetErrorCode"> + <owner>justincohen@chromium.org</owner> + <summary> + HTTP Response code returned by the server when trying to fetch the OAuth + token for a desktop ios promotion query. + </summary> +</histogram> + <histogram name="DesktopIOSPromotion.SMSToSigninTime" units="hours"> <owner>mrefaat@chromium.org</owner> <summary> @@ -17762,6 +17793,14 @@ </summary> </histogram> +<histogram name="Extensions.LoadOffStoreItems" units="Number of items"> + <owner>rdevlin.cronin@chromium.org</owner> + <summary> + The number of enabled extensions or apps the user has installed that do not + update from the Chrome Web Store. Recorded during profile initialization. + </summary> +</histogram> + <histogram name="Extensions.LoadPackagedApp"> <owner>rdevlin.cronin@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/presubmit_bad_message_reasons.py b/tools/metrics/histograms/presubmit_bad_message_reasons.py new file mode 100644 index 0000000..0548607 --- /dev/null +++ b/tools/metrics/histograms/presubmit_bad_message_reasons.py
@@ -0,0 +1,38 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Check to see if the various BadMessage enums in histograms.xml need to be +updated. This can be called from a chromium PRESUBMIT.py to ensure updates to +bad_message.h also include the generated changes to histograms.xml +""" + +import update_histogram_enum + +def PrecheckBadMessage(input_api, output_api, histogram_name): + source_path = '' + + # This function is called once per bad_message.h-containing directory. Check + # for the |bad_message.h| file, and if present, remember its path. + for f in input_api.AffectedFiles(): + if f.LocalPath().endswith('bad_message.h'): + source_path = f.LocalPath() + break + + # If the |bad_message.h| wasn't found in this change, then there is nothing to + # do and histogram.xml does not need to be updated. + if source_path == '': + return [] + + START_MARKER='^enum (class )?BadMessageReason {' + END_MARKER='^BAD_MESSAGE_MAX' + if update_histogram_enum.HistogramNeedsUpdate( + histogram_enum_name=histogram_name, + source_enum_path=source_path, + start_marker=START_MARKER, + end_marker=END_MARKER): + return [output_api.PresubmitPromptWarning( + 'bad_messages.h has been updated but histogram.xml does not ' + 'appear to be updated.\nPlease run:\n' + ' python tools/metrics/histograms/update_bad_message_reasons.py\n')] + return []
diff --git a/tools/perf/page_sets/tough_ad_cases.py b/tools/perf/page_sets/tough_ad_cases.py index d9ea110c..68321d1 100644 --- a/tools/perf/page_sets/tough_ad_cases.py +++ b/tools/perf/page_sets/tough_ad_cases.py
@@ -189,9 +189,8 @@ self, scroll=scroll)) self.AddStory(AdPage('http://androidcentral.com', self, scroll=scroll, wait_for_interactive_or_better=True)) - # Disabled: crbug.com/682349 - #self.AddStory(AdPage('http://mashable.com', self, scroll=scroll, - # y_scroll_distance_multiplier=0.25)) + self.AddStory(AdPage('http://mashable.com', self, scroll=scroll, + y_scroll_distance_multiplier=0.25)) self.AddStory(AdPage('http://www.androidauthority.com/' 'reduce-data-use-turn-on-data-compression-in-chrome-630064/', self, scroll=scroll))