diff --git a/DEPS b/DEPS index 75a906d..5f4c80fd 100644 --- a/DEPS +++ b/DEPS
@@ -44,7 +44,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '09e2ca1bb70f4735b300f293a8885d3be8fecfe2', + 'v8_revision': 'b3ab49fff913807d151e289dc44b3fb91201997d', # 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. @@ -52,7 +52,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '38ef7c8c97d1e28cb52816eedb823438c3057cee', + 'angle_revision': 'a818c327fe6bb770c3a3621a985c4afd698ad0ab', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -64,7 +64,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'db194cf018069b930d0e3d5fc0242e14f70e8620', + 'pdfium_revision': '72f50f2021cd9f66016c962df8d27fc0c34748cd', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -88,7 +88,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling NaCl # and whatever else without interference from each other. - 'nacl_revision': '25f277533941cf6c733ff70ae3e7713423ba60f2', + 'nacl_revision': '9f8fdd668b305511b605ee229533639c29a5222b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype-android # and whatever else without interference from each other. @@ -96,7 +96,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '71960b03052fb5fe3e75024533923e785a465a26', + 'catapult_revision': '4ffd54d31cd52fdcc697562667985eac477a95ce', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other.
diff --git a/ash/common/system/tray/tray_details_view.cc b/ash/common/system/tray/tray_details_view.cc index cd84002..6e1b8739 100644 --- a/ash/common/system/tray/tray_details_view.cc +++ b/ash/common/system/tray/tray_details_view.cc
@@ -49,8 +49,7 @@ // above the top of the visible viewport until the next one "pushes" it up and // are painted above other children. To indicate that a child is a sticky header // row use set_id(VIEW_ID_STICKY_HEADER). -class ScrollContentsView : public views::View, - public views::ViewTargeterDelegate { +class ScrollContentsView : public views::View { public: ScrollContentsView() : box_layout_(new views::BoxLayout( @@ -58,7 +57,6 @@ 0, 0, UseMd() ? 0 : kContentsBetweenChildSpacingNonMd)) { - SetEventTargeter(base::MakeUnique<views::ViewTargeter>(this)); SetLayoutManager(box_layout_); } ~ScrollContentsView() override {} @@ -70,17 +68,11 @@ } void PaintChildren(const ui::PaintContext& context) override { - for (int i = 0; i < child_count(); ++i) { - if (child_at(i)->id() != VIEW_ID_STICKY_HEADER && !child_at(i)->layer()) - child_at(i)->Paint(context); - } + views::View::PaintChildren(context); bool did_draw_shadow = false; - // Paint header rows above other children in Z-order. - for (auto& header : headers_) { - if (!header.view->layer()) - header.view->Paint(context); + // Paint header row separators. + for (auto& header : headers_) did_draw_shadow = PaintDelineation(header, context) || did_draw_shadow; - } // Draw a shadow at the top of the viewport when scrolled, but only if a // header didn't already draw one. Overlap the shadow with the separator @@ -101,24 +93,20 @@ PositionHeaderRows(); } - void ReorderChildLayers(ui::Layer* parent_layer) override { - views::View::ReorderChildLayers(parent_layer); - ui::Layer* topmost_layer = TopmostLayer(this, parent_layer); - if (!topmost_layer) - return; - - // Keep the sticky headers with layers above the rest of the children's - // layers. Make sure to avoid changing the stacking order of the layers that - // are children of |parent_layer| but do not belong to the same parent view. - // Note: this assumes that all views that have id=VIEW_ID_STICKY_HEADER have - // a layer. - for (int i = child_count() - 1; i >= 0; --i) { - View* child = child_at(i); - if (child->id() == VIEW_ID_STICKY_HEADER && - child->layer() != topmost_layer) { - parent_layer->StackAbove(child->layer(), topmost_layer); - } + View::Views GetChildrenInZOrder() override { + View::Views children; + // Iterate over regular children and later over the sticky headers to keep + // the sticky headers above in Z-order. + for (int i = 0; i < child_count(); ++i) { + if (child_at(i)->id() != VIEW_ID_STICKY_HEADER) + children.push_back(child_at(i)); } + for (int i = 0; i < child_count(); ++i) { + if (child_at(i)->id() == VIEW_ID_STICKY_HEADER) + children.push_back(child_at(i)); + } + DCHECK_EQ(child_count(), static_cast<int>(children.size())); + return children; } void ViewHierarchyChanged( @@ -144,19 +132,6 @@ } } - // views::ViewTargeterDelegate: - View* TargetForRect(View* root, const gfx::Rect& rect) override { - // Give header rows first dibs on events. - for (auto& header : headers_) { - views::View* view = header.view; - gfx::Rect local_to_header = rect; - local_to_header.Offset(-view->x(), -view->y()); - if (ViewTargeterDelegate::DoesIntersectRect(view, local_to_header)) - return ViewTargeterDelegate::TargetForRect(view, local_to_header); - } - return ViewTargeterDelegate::TargetForRect(root, rect); - } - private: const SkColor kSeparatorColor = SkColorSetA(SK_ColorBLACK, 0x1F); const int kShadowOffsetY = 2; @@ -251,25 +226,6 @@ canvas->DrawRect(shadowed_area, paint); } - // Recursively iterates through children to return the child layer that is - // stacked at the top. Only considers layers that are direct |parent_layer|'s - // children. - ui::Layer* TopmostLayer(views::View* view, ui::Layer* parent_layer) { - DCHECK(parent_layer); - // Iterate backwards through the children to find the topmost layer. - for (int i = view->child_count() - 1; i >= 0; --i) { - views::View* child = view->child_at(i); - ui::Layer* layer = TopmostLayer(child, parent_layer); - if (layer) - return layer; - } - if (view->layer() && view->layer() != parent_layer && - view->layer()->parent() == parent_layer) { - return view->layer(); - } - return nullptr; - } - views::BoxLayout* box_layout_; // Header child views that stick to the top of visible viewport when scrolled.
diff --git a/ash/common/wm/window_cycle_controller.cc b/ash/common/wm/window_cycle_controller.cc index 5a0ede9..17fb0448 100644 --- a/ash/common/wm/window_cycle_controller.cc +++ b/ash/common/wm/window_cycle_controller.cc
@@ -78,6 +78,15 @@ window_list.size()); } +void WindowCycleController::CompleteCycling() { + window_cycle_list_->set_user_did_accept(true); + StopCycling(); +} + +void WindowCycleController::CancelCycling() { + StopCycling(); +} + ////////////////////////////////////////////////////////////////////////////// // WindowCycleController, private:
diff --git a/ash/common/wm/window_cycle_controller.h b/ash/common/wm/window_cycle_controller.h index 4544f49..87eedd9 100644 --- a/ash/common/wm/window_cycle_controller.h +++ b/ash/common/wm/window_cycle_controller.h
@@ -45,10 +45,14 @@ // listen to the alt key release. void StartCycling(); - // Stops the current window cycle and removes the event filter. - void StopCycling(); + // Both of these functions stop the current window cycle and removes the event + // filter. The former indicates success (i.e. the new window should be + // activated) and the latter indicates that the interaction was cancelled (and + // the originally active window should remain active). + void CompleteCycling(); + void CancelCycling(); - // Returns the WindowCycleList. Really only useful for testing. + // Returns the WindowCycleList. const WindowCycleList* window_cycle_list() const { return window_cycle_list_.get(); } @@ -57,6 +61,8 @@ // Cycles to the next or previous window based on |direction|. void Step(Direction direction); + void StopCycling(); + std::unique_ptr<WindowCycleList> window_cycle_list_; // Tracks what Window was active when starting to cycle and used to determine
diff --git a/ash/common/wm/window_cycle_list.cc b/ash/common/wm/window_cycle_list.cc index b8b1337a..6ba2e9a 100644 --- a/ash/common/wm/window_cycle_list.cc +++ b/ash/common/wm/window_cycle_list.cc
@@ -39,17 +39,6 @@ // Used for the highlight view and the shield (black background). constexpr float kBackgroundCornerRadius = 4.f; -// Returns the window immediately below |window| in the current container. -WmWindow* GetWindowBelow(WmWindow* window) { - WmWindow* parent = window->GetParent(); - if (!parent) - return nullptr; - const WmWindow::Windows children = parent->GetChildren(); - auto iter = std::find(children.begin(), children.end(), window); - CHECK(*iter == window); - return (iter != children.begin()) ? *(iter - 1) : nullptr; -} - // This background paints a |Painter| but fills the view's layer's size rather // than the view's size. class LayerFillBackgroundPainter : public views::Background { @@ -72,36 +61,6 @@ } // namespace -// This class restores and moves a window to the front of the stacking order for -// the duration of the class's scope. -class ScopedShowWindow : public WmWindowObserver { - public: - ScopedShowWindow(); - ~ScopedShowWindow() override; - - // Show |window| at the top of the stacking order. - void Show(WmWindow* window); - - // Cancel restoring the window on going out of scope. - void CancelRestore(); - - private: - // WmWindowObserver: - void OnWindowTreeChanging(WmWindow* window, - const TreeChangeParams& params) override; - - // The window being shown. - WmWindow* window_; - - // The window immediately below where window_ belongs. - WmWindow* stack_window_above_; - - // If true, minimize window_ on going out of scope. - bool minimized_; - - DISALLOW_COPY_AND_ASSIGN(ScopedShowWindow); -}; - // This view represents a single WmWindow by displaying a title and a thumbnail // of the window's contents. class WindowPreviewView : public views::View, public WmWindowObserver { @@ -392,7 +351,7 @@ } void OnMouseCaptureLost() override { - WmShell::Get()->window_cycle_controller()->StopCycling(); + WmShell::Get()->window_cycle_controller()->CancelCycling(); } void OnPaintBackground(gfx::Canvas* canvas) override { @@ -425,62 +384,8 @@ DISALLOW_COPY_AND_ASSIGN(WindowCycleView); }; -ScopedShowWindow::ScopedShowWindow() - : window_(nullptr), stack_window_above_(nullptr), minimized_(false) {} - -ScopedShowWindow::~ScopedShowWindow() { - if (window_) { - window_->GetParent()->RemoveObserver(this); - - // Restore window's stacking position. - if (stack_window_above_) - window_->GetParent()->StackChildAbove(window_, stack_window_above_); - else - window_->GetParent()->StackChildAtBottom(window_); - - // Restore minimized state. - if (minimized_) - window_->GetWindowState()->Minimize(); - } -} - -void ScopedShowWindow::Show(WmWindow* window) { - DCHECK(!window_); - window_ = window; - stack_window_above_ = GetWindowBelow(window); - minimized_ = window->GetWindowState()->IsMinimized(); - window_->GetParent()->AddObserver(this); - window_->Show(); - window_->GetWindowState()->Activate(); -} - -void ScopedShowWindow::CancelRestore() { - if (!window_) - return; - window_->GetParent()->RemoveObserver(this); - window_ = stack_window_above_ = nullptr; -} - -void ScopedShowWindow::OnWindowTreeChanging(WmWindow* window, - const TreeChangeParams& params) { - // Only interested in removal. - if (params.new_parent != nullptr) - return; - - if (params.target == window_) { - CancelRestore(); - } else if (params.target == stack_window_above_) { - // If the window this window was above is removed, use the next window down - // as the restore marker. - stack_window_above_ = GetWindowBelow(stack_window_above_); - } -} - WindowCycleList::WindowCycleList(const WindowList& windows) : windows_(windows), - current_index_(0), - cycle_view_(nullptr), - cycle_ui_widget_(nullptr), screen_observer_(this) { if (!ShouldShowUi()) WmShell::Get()->mru_window_tracker()->SetIgnoreActivations(true); @@ -505,9 +410,7 @@ for (WmWindow* window : windows_) window->RemoveObserver(this); - if (showing_window_) { - showing_window_->CancelRestore(); - } else if (!windows_.empty()) { + if (!windows_.empty() && user_did_accept_) { WmWindow* target_window = windows_[current_index_]; target_window->Show(); target_window->GetWindowState()->Activate(); @@ -553,10 +456,6 @@ if (cycle_view_) cycle_view_->SetTargetWindow(windows_[current_index_]); - } else { - // Make sure the next window is visible. - showing_window_.reset(new ScopedShowWindow); - showing_window_->Show(windows_[current_index_]); } } @@ -584,7 +483,7 @@ cycle_view_->HandleWindowDestruction(window, new_target_window); if (windows_.empty()) { // This deletes us. - WmShell::Get()->window_cycle_controller()->StopCycling(); + WmShell::Get()->window_cycle_controller()->CancelCycling(); return; } } @@ -602,7 +501,7 @@ ->GetDisplayNearestWindow(cycle_ui_widget_->GetNativeView()) .id() && (changed_metrics & (DISPLAY_METRIC_BOUNDS | DISPLAY_METRIC_ROTATION))) { - WmShell::Get()->window_cycle_controller()->StopCycling(); + WmShell::Get()->window_cycle_controller()->CancelCycling(); // |this| is deleted. return; }
diff --git a/ash/common/wm/window_cycle_list.h b/ash/common/wm/window_cycle_list.h index d4bc8d06..c950a73 100644 --- a/ash/common/wm/window_cycle_list.h +++ b/ash/common/wm/window_cycle_list.h
@@ -26,7 +26,6 @@ namespace ash { -class ScopedShowWindow; class WindowCycleView; // Tracks a set of Windows that can be stepped through. This class is used by @@ -46,6 +45,10 @@ int current_index() const { return current_index_; } + void set_user_did_accept(bool user_did_accept) { + user_did_accept_ = user_did_accept; + } + private: friend class WindowCycleControllerTest; @@ -79,19 +82,18 @@ // Current position in the |windows_|. Can be used to query selection depth, // i.e., the position of an active window in a global MRU ordering. - int current_index_; + int current_index_ = 0; - // Wrapper for the window brought to the front. - // TODO(estade): remove ScopedShowWindow when we know we are happy launching - // the |cycle_view_| version. - std::unique_ptr<ScopedShowWindow> showing_window_; + // True if the user accepted the window switch (as opposed to cancelling or + // interrupting the interaction). + bool user_did_accept_ = false; // The top level View for the window cycle UI. May be null if the UI is not // showing. - WindowCycleView* cycle_view_; + WindowCycleView* cycle_view_ = nullptr; // The widget that hosts the window cycle UI. - views::Widget* cycle_ui_widget_; + views::Widget* cycle_ui_widget_ = nullptr; // The window list will dismiss if the display metrics change. ScopedObserver<display::Screen, display::DisplayObserver> screen_observer_;
diff --git a/ash/wm/window_cycle_controller_unittest.cc b/ash/wm/window_cycle_controller_unittest.cc index 28ca6b1c..2223ec5e 100644 --- a/ash/wm/window_cycle_controller_unittest.cc +++ b/ash/wm/window_cycle_controller_unittest.cc
@@ -170,13 +170,18 @@ ASSERT_EQ(window1.get(), GetWindows(controller)[1]); ASSERT_EQ(window2.get(), GetWindows(controller)[2]); - controller->StopCycling(); + controller->CompleteCycling(); EXPECT_TRUE(wm::IsActiveWindow(window1.get())); // Pressing and releasing Alt-tab again should cycle back to the most- // recently-used window in the current child order. controller->HandleCycleWindow(WindowCycleController::FORWARD); - controller->StopCycling(); + controller->CompleteCycling(); + EXPECT_TRUE(wm::IsActiveWindow(window0.get())); + + // Cancelled cycling shouldn't move the active window. + controller->HandleCycleWindow(WindowCycleController::FORWARD); + controller->CancelCycling(); EXPECT_TRUE(wm::IsActiveWindow(window0.get())); // Pressing Alt-tab multiple times without releasing Alt should cycle through @@ -190,7 +195,7 @@ controller->HandleCycleWindow(WindowCycleController::FORWARD); EXPECT_TRUE(controller->IsCycling()); - controller->StopCycling(); + controller->CompleteCycling(); EXPECT_FALSE(controller->IsCycling()); EXPECT_TRUE(wm::IsActiveWindow(window0.get())); @@ -202,7 +207,7 @@ // Likewise we can cycle backwards through the windows. controller->HandleCycleWindow(WindowCycleController::BACKWARD); controller->HandleCycleWindow(WindowCycleController::BACKWARD); - controller->StopCycling(); + controller->CompleteCycling(); EXPECT_TRUE(wm::IsActiveWindow(window1.get())); // Reset our stacking order. @@ -221,7 +226,7 @@ EXPECT_TRUE(wm::IsActiveWindow(window0.get())); controller->HandleCycleWindow(WindowCycleController::FORWARD); controller->HandleCycleWindow(WindowCycleController::FORWARD); - controller->StopCycling(); + controller->CompleteCycling(); EXPECT_TRUE(wm::IsActiveWindow(window2.get())); // When a modal window is active, cycling window does not take effect. @@ -259,13 +264,13 @@ // Rotate focus, this should move focus to window0. WindowCycleController* controller = WmShell::Get()->window_cycle_controller(); controller->HandleCycleWindow(WindowCycleController::FORWARD); - controller->StopCycling(); + controller->CompleteCycling(); EXPECT_TRUE(wm::GetWindowState(window0.get())->IsActive()); EXPECT_FALSE(window1_state->IsActive()); // One more time. controller->HandleCycleWindow(WindowCycleController::FORWARD); - controller->StopCycling(); + controller->CompleteCycling(); EXPECT_TRUE(window1_state->IsActive()); } @@ -284,14 +289,14 @@ // Rotate focus, this should move focus to window1 and unminimize it. WindowCycleController* controller = WmShell::Get()->window_cycle_controller(); controller->HandleCycleWindow(WindowCycleController::FORWARD); - controller->StopCycling(); + controller->CompleteCycling(); EXPECT_FALSE(window0_state->IsActive()); EXPECT_FALSE(window1_state->IsMinimized()); EXPECT_TRUE(window1_state->IsActive()); // One more time back to w0. controller->HandleCycleWindow(WindowCycleController::FORWARD); - controller->StopCycling(); + controller->CompleteCycling(); EXPECT_TRUE(window0_state->IsActive()); } @@ -309,7 +314,7 @@ WindowCycleController* controller = WmShell::Get()->window_cycle_controller(); controller->HandleCycleWindow(WindowCycleController::FORWARD); - controller->StopCycling(); + controller->CompleteCycling(); EXPECT_TRUE(window0_state->IsActive()); EXPECT_FALSE(window0_state->IsMinimized()); EXPECT_TRUE(window1_state->IsMinimized()); @@ -318,7 +323,7 @@ window0_state->Minimize(); window1_state->Minimize(); controller->HandleCycleWindow(WindowCycleController::BACKWARD); - controller->StopCycling(); + controller->CompleteCycling(); EXPECT_TRUE(window0_state->IsMinimized()); EXPECT_TRUE(window1_state->IsActive()); EXPECT_FALSE(window1_state->IsMinimized()); @@ -347,7 +352,7 @@ EXPECT_EQ(window2.get(), GetWindows(controller)[1]); EXPECT_EQ(window1.get(), GetWindows(controller)[2]); - controller->StopCycling(); + controller->CompleteCycling(); } TEST_F(WindowCycleControllerTest, AlwaysOnTopMultiWindow) { @@ -375,7 +380,7 @@ EXPECT_EQ(window2.get(), GetWindows(controller)[2]); EXPECT_EQ(window1.get(), GetWindows(controller)[3]); - controller->StopCycling(); + controller->CompleteCycling(); } TEST_F(WindowCycleControllerTest, AlwaysOnTopMultipleRootWindows) { @@ -427,7 +432,7 @@ EXPECT_EQ(window1.get(), GetWindows(controller)[2]); EXPECT_EQ(window0.get(), GetWindows(controller)[3]); - controller->StopCycling(); + controller->CompleteCycling(); } TEST_F(WindowCycleControllerTest, MostRecentlyUsed) { @@ -453,17 +458,17 @@ // Cycling through then stopping the cycling will activate a window. controller->HandleCycleWindow(WindowCycleController::FORWARD); - controller->StopCycling(); + controller->CompleteCycling(); EXPECT_TRUE(wm::IsActiveWindow(window1.get())); - // Cycling alone (without StopCycling()) doesn't activate. + // Cycling alone (without CompleteCycling()) doesn't activate. controller->HandleCycleWindow(WindowCycleController::FORWARD); EXPECT_FALSE(wm::IsActiveWindow(window0.get())); // Showing the Alt+Tab UI does however deactivate the erstwhile active window. EXPECT_FALSE(wm::IsActiveWindow(window1.get())); - controller->StopCycling(); + controller->CompleteCycling(); } // Tests that beginning window selection hides the app list. @@ -482,7 +487,7 @@ EXPECT_FALSE(wm::IsActiveWindow(window0.get())); EXPECT_FALSE(wm::IsActiveWindow(window1.get())); - controller->StopCycling(); + controller->CompleteCycling(); } // Tests that cycling through windows doesn't change their minimized state. @@ -504,7 +509,7 @@ controller->HandleCycleWindow(WindowCycleController::FORWARD); EXPECT_TRUE(IsWindowMinimized(window1.get())); - controller->StopCycling(); + controller->CompleteCycling(); EXPECT_TRUE(IsWindowMinimized(window1.get())); } @@ -522,18 +527,18 @@ EXPECT_TRUE(wm::IsActiveWindow(panel0.get())); controller->HandleCycleWindow(WindowCycleController::FORWARD); - controller->StopCycling(); + controller->CompleteCycling(); EXPECT_TRUE(wm::IsActiveWindow(panel1.get())); // Cycling again should select the most recently used panel. controller->HandleCycleWindow(WindowCycleController::FORWARD); - controller->StopCycling(); + controller->CompleteCycling(); EXPECT_TRUE(wm::IsActiveWindow(panel0.get())); // Cycling twice again should select the first window. controller->HandleCycleWindow(WindowCycleController::FORWARD); controller->HandleCycleWindow(WindowCycleController::FORWARD); - controller->StopCycling(); + controller->CompleteCycling(); EXPECT_TRUE(wm::IsActiveWindow(window0.get())); } @@ -560,7 +565,7 @@ panel1.reset(); // Cycling again should now select window2. controller->HandleCycleWindow(WindowCycleController::FORWARD); - controller->StopCycling(); + controller->CompleteCycling(); EXPECT_TRUE(wm::IsActiveWindow(window2.get())); } @@ -586,7 +591,7 @@ panel0.reset(); // Cycling again should now select panel1. controller->HandleCycleWindow(WindowCycleController::FORWARD); - controller->StopCycling(); + controller->CompleteCycling(); EXPECT_TRUE(wm::IsActiveWindow(panel1.get())); } @@ -637,7 +642,7 @@ EXPECT_EQ(0, event_count.GetMouseEventCountAndReset()); // Stop cycling: once again, events get through. - controller->StopCycling(); + controller->CompleteCycling(); generator.ClickLeftButton(); EXPECT_LT(0, event_count.GetMouseEventCountAndReset()); }
diff --git a/ash/wm/window_cycle_event_filter_aura.cc b/ash/wm/window_cycle_event_filter_aura.cc index fbafa859..e9879b52 100644 --- a/ash/wm/window_cycle_event_filter_aura.cc +++ b/ash/wm/window_cycle_event_filter_aura.cc
@@ -5,6 +5,7 @@ #include "ash/wm/window_cycle_event_filter_aura.h" #include "ash/common/wm/window_cycle_controller.h" +#include "ash/common/wm/window_cycle_list.h" #include "ash/common/wm_shell.h" #include "ash/shell.h" #include "ui/events/event.h" @@ -30,7 +31,7 @@ // Views uses VKEY_MENU for both left and right Alt keys. if (event->key_code() == ui::VKEY_MENU && event->type() == ui::ET_KEY_RELEASED) { - WmShell::Get()->window_cycle_controller()->StopCycling(); + WmShell::Get()->window_cycle_controller()->CompleteCycling(); // Warning: |this| will be deleted from here on. } else if (event->key_code() == ui::VKEY_TAB) { if (event->type() == ui::ET_KEY_RELEASED) { @@ -46,7 +47,7 @@ : WindowCycleController::FORWARD)); } } else if (event->key_code() == ui::VKEY_ESCAPE) { - WmShell::Get()->window_cycle_controller()->StopCycling(); + WmShell::Get()->window_cycle_controller()->CancelCycling(); } }
diff --git a/base/numerics/safe_math.h b/base/numerics/safe_math.h index 32f0dfdd..f5007db3 100644 --- a/base/numerics/safe_math.h +++ b/base/numerics/safe_math.h
@@ -204,27 +204,26 @@ template <typename Src> CheckedNumeric& operator^=(const Src rhs); - CheckedNumeric operator-() const { - // Negation is always valid for floating point. - T value = 0; - bool is_valid = (std::is_floating_point<T>::value || IsValid()) && - CheckedNeg(state_.value(), &value); - return CheckedNumeric<T>(value, is_valid); + constexpr CheckedNumeric operator-() const { + return CheckedNumeric<T>( + NegateWrapper(state_.value()), + IsValid() && + (!std::is_signed<T>::value || std::is_floating_point<T>::value || + NegateWrapper(state_.value()) != + std::numeric_limits<T>::lowest())); } - CheckedNumeric operator~() const { - static_assert(!std::is_signed<T>::value, "Type must be unsigned."); - T value = 0; - bool is_valid = IsValid() && CheckedInv(state_.value(), &value); - return CheckedNumeric<T>(value, is_valid); + constexpr CheckedNumeric operator~() const { + return CheckedNumeric<decltype(InvertWrapper(T()))>( + InvertWrapper(state_.value()), IsValid()); } - CheckedNumeric Abs() const { - // Absolute value is always valid for floating point. - T value = 0; - bool is_valid = (std::is_floating_point<T>::value || IsValid()) && - CheckedAbs(state_.value(), &value); - return CheckedNumeric<T>(value, is_valid); + constexpr CheckedNumeric Abs() const { + return CheckedNumeric<T>( + AbsWrapper(state_.value()), + IsValid() && + (!std::is_signed<T>::value || std::is_floating_point<T>::value || + AbsWrapper(state_.value()) != std::numeric_limits<T>::lowest())); } template <typename U>
diff --git a/base/numerics/safe_math_impl.h b/base/numerics/safe_math_impl.h index 9956115..a224f69 100644 --- a/base/numerics/safe_math_impl.h +++ b/base/numerics/safe_math_impl.h
@@ -442,54 +442,6 @@ } }; -template <typename T, - typename std::enable_if<std::is_integral<T>::value && - std::is_signed<T>::value>::type* = nullptr> -bool CheckedNeg(T value, T* result) { - // The negation of signed min is min, so catch that one. - if (value != std::numeric_limits<T>::lowest()) { - *result = static_cast<T>(-value); - return true; - } - return false; -} - -template <typename T, - typename std::enable_if<std::is_integral<T>::value && - !std::is_signed<T>::value>::type* = nullptr> -bool CheckedNeg(T value, T* result) { - if (!value) { - *result = static_cast<T>(0); - return true; - } - return false; -} - -template <typename T, - typename std::enable_if<std::is_integral<T>::value && - !std::is_signed<T>::value>::type* = nullptr> -bool CheckedInv(T value, T* result) { - *result = ~value; - return true; -} - -template <typename T, - typename std::enable_if<std::is_integral<T>::value && - std::is_signed<T>::value>::type* = nullptr> -bool CheckedAbs(T value, T* result) { - *result = static_cast<T>(SafeUnsignedAbs(value)); - return *result != std::numeric_limits<T>::lowest(); -} - -template <typename T, - typename std::enable_if<std::is_integral<T>::value && - !std::is_signed<T>::value>::type* = nullptr> -bool CheckedAbs(T value, T* result) { - // T is unsigned, so |value| must already be positive. - *result = value; - return true; -} - // This is just boilerplate that wraps the standard floating point arithmetic. // A macro isn't the nicest solution, but it beats rewriting these repeatedly. #define BASE_FLOAT_ARITHMETIC_OPS(NAME, OP) \ @@ -514,20 +466,43 @@ #undef BASE_FLOAT_ARITHMETIC_OPS -template < - typename T, - typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr> -bool CheckedNeg(T value, T* result) { - *result = static_cast<T>(-value); - return true; +// Wrap the unary operations to allow SFINAE when instantiating integrals versus +// floating points. These don't perform any overflow checking. Rather, they +// exhibit well-defined overflow semantics and rely on the caller to detect +// if an overflow occured. + +template <typename T, + typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> +constexpr T NegateWrapper(T value) { + using UnsignedT = typename std::make_unsigned<T>::type; + // This will compile to a NEG on Intel, and is normal negation on ARM. + return static_cast<T>(UnsignedT(0) - static_cast<UnsignedT>(value)); } template < typename T, typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr> -bool CheckedAbs(T value, T* result) { - *result = static_cast<T>(std::abs(value)); - return true; +constexpr T NegateWrapper(T value) { + return -value; +} + +template <typename T, + typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> +constexpr typename std::make_unsigned<T>::type InvertWrapper(T value) { + return ~value; +} + +template <typename T, + typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> +constexpr T AbsWrapper(T value) { + return static_cast<T>(SafeUnsignedAbs(value)); +} + +template < + typename T, + typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr> +constexpr T AbsWrapper(T value) { + return value < 0 ? -value : value; } // Floats carry around their validity state with them, but integers do not. So,
diff --git a/build/android/pylib/local/device/local_device_perf_test_run.py b/build/android/pylib/local/device/local_device_perf_test_run.py index b34c360..0dbafd5 100644 --- a/build/android/pylib/local/device/local_device_perf_test_run.py +++ b/build/android/pylib/local/device/local_device_perf_test_run.py
@@ -252,7 +252,12 @@ self._TestTearDown() if result_type != base_test_result.ResultType.PASS: try: - device_recovery.RecoverDevice(self._device, self._env.blacklist) + # TODO(rnephew): Possible problem when restarting on N7 devices. + # Determine if this is true. crbug.com/667470 + if 'Nexus 7' not in self._device.product_model: + device_recovery.RecoverDevice(self._device, self._env.blacklist) + else: + logging.critical('Not attempting device recovery.') except device_errors.CommandTimeoutError: logging.exception( 'Device failed to recover after failing %s.', test)
diff --git a/cc/output/shader.cc b/cc/output/shader.cc index 0918a7c22..1a7332d 100644 --- a/cc/output/shader.cc +++ b/cc/output/shader.cc
@@ -7,6 +7,7 @@ #include <stddef.h> #include <algorithm> +#include <vector> #include "base/logging.h" #include "base/strings/stringprintf.h" @@ -765,12 +766,7 @@ backdrop_rect_location_ = locations[POS + 2]; \ } -FragmentShaderBase::FragmentShaderBase() - : backdrop_location_(-1), - original_backdrop_location_(-1), - backdrop_rect_location_(-1), - blend_mode_(BLEND_MODE_NONE), - mask_for_background_(false) {} +FragmentShaderBase::FragmentShaderBase() {} std::string FragmentShaderBase::GetShaderString(TexCoordPrecision precision, SamplerType sampler) const { @@ -779,6 +775,91 @@ sampler, SetBlendModeFunctions(GetShaderSource()))); } +void FragmentShaderBase::Init(GLES2Interface* context, + unsigned program, + int* base_uniform_index) { + std::vector<const char*> uniforms; + std::vector<int> locations; + if (has_blend_mode()) { + uniforms.push_back("s_backdropTexture"); + uniforms.push_back("s_originalBackdropTexture"); + uniforms.push_back("backdropRect"); + } + if (has_mask_sampler_) { + uniforms.push_back("s_mask"); + uniforms.push_back("maskTexCoordScale"); + uniforms.push_back("maskTexCoordOffset"); + } + if (has_color_matrix_) { + uniforms.push_back("colorMatrix"); + uniforms.push_back("colorOffset"); + } + if (has_sampler_) + uniforms.push_back("s_texture"); + if (has_uniform_alpha_) + uniforms.push_back("alpha"); + if (has_background_color_) + uniforms.push_back("background_color"); + if (has_fragment_tex_transform_) + uniforms.push_back("fragmentTexTransform"); + if (has_uniform_color_) + uniforms.push_back("color"); + + locations.resize(uniforms.size()); + + GetProgramUniformLocations(context, program, uniforms.size(), uniforms.data(), + locations.data(), base_uniform_index); + + size_t index = 0; + if (has_blend_mode()) { + backdrop_location_ = locations[index++]; + original_backdrop_location_ = locations[index++]; + backdrop_rect_location_ = locations[index++]; + } + if (has_mask_sampler_) { + mask_sampler_location_ = locations[index++]; + mask_tex_coord_scale_location_ = locations[index++]; + mask_tex_coord_offset_location_ = locations[index++]; + } + if (has_color_matrix_) { + color_matrix_location_ = locations[index++]; + color_offset_location_ = locations[index++]; + } + if (has_sampler_) + sampler_location_ = locations[index++]; + if (has_uniform_alpha_) + alpha_location_ = locations[index++]; + if (has_background_color_) + background_color_location_ = locations[index++]; + if (has_fragment_tex_transform_) + fragment_tex_transform_location_ = locations[index++]; + if (has_uniform_color_) + color_location_ = locations[index++]; + DCHECK_EQ(index, locations.size()); +} + +void FragmentShaderBase::FillLocations(ShaderLocations* locations) const { + if (has_blend_mode()) { + locations->backdrop = backdrop_location_; + locations->backdrop_rect = backdrop_rect_location_; + } + if (mask_for_background()) + locations->original_backdrop = original_backdrop_location_; + if (has_mask_sampler_) { + locations->mask_sampler = mask_sampler_location_; + locations->mask_tex_coord_scale = mask_tex_coord_scale_location_; + locations->mask_tex_coord_offset = mask_tex_coord_offset_location_; + } + if (has_color_matrix_) { + locations->color_matrix = color_matrix_location_; + locations->color_offset = color_offset_location_; + } + if (has_sampler_) + locations->sampler = sampler_location_; + if (has_uniform_alpha_) + locations->alpha = alpha_location_; +} + std::string FragmentShaderBase::SetBlendModeFunctions( const std::string& shader_string) const { if (shader_string.find("ApplyBlendMode") == std::string::npos) @@ -1074,77 +1155,6 @@ return "result = vec4(1.0, 0.0, 0.0, 1.0);"; } -FragmentTexAlphaBinding::FragmentTexAlphaBinding() - : sampler_location_(-1), alpha_location_(-1) { -} - -void FragmentTexAlphaBinding::Init(GLES2Interface* context, - unsigned program, - int* base_uniform_index) { - static const char* uniforms[] = { - "s_texture", "alpha", BLEND_MODE_UNIFORMS, - }; - int locations[arraysize(uniforms)]; - - GetProgramUniformLocations(context, - program, - arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS, - uniforms, - locations, - base_uniform_index); - sampler_location_ = locations[0]; - alpha_location_ = locations[1]; - BLEND_MODE_SET_LOCATIONS(locations, 2); -} - -FragmentTexColorMatrixAlphaBinding::FragmentTexColorMatrixAlphaBinding() - : sampler_location_(-1), - alpha_location_(-1), - color_matrix_location_(-1), - color_offset_location_(-1) { -} - -void FragmentTexColorMatrixAlphaBinding::Init(GLES2Interface* context, - unsigned program, - int* base_uniform_index) { - static const char* uniforms[] = { - "s_texture", "alpha", "colorMatrix", "colorOffset", BLEND_MODE_UNIFORMS, - }; - int locations[arraysize(uniforms)]; - - GetProgramUniformLocations(context, - program, - arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS, - uniforms, - locations, - base_uniform_index); - sampler_location_ = locations[0]; - alpha_location_ = locations[1]; - color_matrix_location_ = locations[2]; - color_offset_location_ = locations[3]; - BLEND_MODE_SET_LOCATIONS(locations, 4); -} - -FragmentTexOpaqueBinding::FragmentTexOpaqueBinding() : sampler_location_(-1) { -} - -void FragmentTexOpaqueBinding::Init(GLES2Interface* context, - unsigned program, - int* base_uniform_index) { - static const char* uniforms[] = { - "s_texture", - }; - int locations[arraysize(uniforms)]; - - GetProgramUniformLocations(context, - program, - arraysize(uniforms), - uniforms, - locations, - base_uniform_index); - sampler_location_ = locations[0]; -} - std::string FragmentShaderRGBATexAlpha::GetShaderSource() const { return SHADER0([]() { precision mediump float; @@ -1158,14 +1168,6 @@ }); } -void FragmentShaderRGBATexAlpha::FillLocations( - ShaderLocations* locations) const { - locations->sampler = sampler_location(); - locations->alpha = alpha_location(); - locations->backdrop = backdrop_location(); - locations->backdrop_rect = backdrop_rect_location(); -} - std::string FragmentShaderRGBATexColorMatrixAlpha::GetShaderSource() const { return SHADER0([]() { precision mediump float; @@ -1186,16 +1188,6 @@ }); } -void FragmentShaderRGBATexColorMatrixAlpha::FillLocations( - ShaderLocations* locations) const { - locations->sampler = sampler_location(); - locations->alpha = alpha_location(); - locations->color_matrix = color_matrix_location(); - locations->color_offset = color_offset_location(); - locations->backdrop = backdrop_location(); - locations->backdrop_rect = backdrop_rect_location(); -} - std::string FragmentShaderRGBATexVaryingAlpha::GetShaderSource() const { return SHADER0([]() { precision mediump float; @@ -1223,32 +1215,6 @@ }); } -FragmentTexBackgroundBinding::FragmentTexBackgroundBinding() - : background_color_location_(-1), sampler_location_(-1) { -} - -void FragmentTexBackgroundBinding::Init(GLES2Interface* context, - unsigned program, - int* base_uniform_index) { - static const char* uniforms[] = { - "s_texture", "background_color", - }; - int locations[arraysize(uniforms)]; - - GetProgramUniformLocations(context, - program, - arraysize(uniforms), - uniforms, - locations, - base_uniform_index); - - sampler_location_ = locations[0]; - DCHECK_NE(sampler_location_, -1); - - background_color_location_ = locations[1]; - DCHECK_NE(background_color_location_, -1); -} - std::string FragmentShaderTexBackgroundVaryingAlpha::GetShaderSource() const { return SHADER0([]() { precision mediump float; @@ -1328,29 +1294,6 @@ }); } -FragmentShaderRGBATexAlphaAA::FragmentShaderRGBATexAlphaAA() - : sampler_location_(-1), alpha_location_(-1) { -} - -void FragmentShaderRGBATexAlphaAA::Init(GLES2Interface* context, - unsigned program, - int* base_uniform_index) { - static const char* uniforms[] = { - "s_texture", "alpha", BLEND_MODE_UNIFORMS, - }; - int locations[arraysize(uniforms)]; - - GetProgramUniformLocations(context, - program, - arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS, - uniforms, - locations, - base_uniform_index); - sampler_location_ = locations[0]; - alpha_location_ = locations[1]; - BLEND_MODE_SET_LOCATIONS(locations, 2); -} - std::string FragmentShaderRGBATexAlphaAA::GetShaderSource() const { return SHADER0([]() { precision mediump float; @@ -1368,39 +1311,6 @@ }); } -void FragmentShaderRGBATexAlphaAA::FillLocations( - ShaderLocations* locations) const { - locations->sampler = sampler_location(); - locations->alpha = alpha_location(); - locations->backdrop = backdrop_location(); - locations->backdrop_rect = backdrop_rect_location(); -} - -FragmentTexClampAlphaAABinding::FragmentTexClampAlphaAABinding() - : sampler_location_(-1), - alpha_location_(-1), - fragment_tex_transform_location_(-1) { -} - -void FragmentTexClampAlphaAABinding::Init(GLES2Interface* context, - unsigned program, - int* base_uniform_index) { - static const char* uniforms[] = { - "s_texture", "alpha", "fragmentTexTransform", - }; - int locations[arraysize(uniforms)]; - - GetProgramUniformLocations(context, - program, - arraysize(uniforms), - uniforms, - locations, - base_uniform_index); - sampler_location_ = locations[0]; - alpha_location_ = locations[1]; - fragment_tex_transform_location_ = locations[2]; -} - std::string FragmentShaderRGBATexClampAlphaAA::GetShaderSource() const { return SHADER0([]() { precision mediump float; @@ -1444,40 +1354,6 @@ }); } -FragmentShaderRGBATexAlphaMask::FragmentShaderRGBATexAlphaMask() - : sampler_location_(-1), - mask_sampler_location_(-1), - alpha_location_(-1), - mask_tex_coord_scale_location_(-1) { -} - -void FragmentShaderRGBATexAlphaMask::Init(GLES2Interface* context, - unsigned program, - int* base_uniform_index) { - static const char* uniforms[] = { - "s_texture", - "s_mask", - "alpha", - "maskTexCoordScale", - "maskTexCoordOffset", - BLEND_MODE_UNIFORMS, - }; - int locations[arraysize(uniforms)]; - - GetProgramUniformLocations(context, - program, - arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS, - uniforms, - locations, - base_uniform_index); - sampler_location_ = locations[0]; - mask_sampler_location_ = locations[1]; - alpha_location_ = locations[2]; - mask_tex_coord_scale_location_ = locations[3]; - mask_tex_coord_offset_location_ = locations[4]; - BLEND_MODE_SET_LOCATIONS(locations, 5); -} - std::string FragmentShaderRGBATexAlphaMask::GetShaderSource() const { return SHADER0([]() { precision mediump float; @@ -1499,54 +1375,6 @@ }); } -void FragmentShaderRGBATexAlphaMask::FillLocations( - ShaderLocations* locations) const { - locations->sampler = sampler_location(); - locations->mask_sampler = mask_sampler_location(); - locations->mask_tex_coord_scale = mask_tex_coord_scale_location(); - locations->mask_tex_coord_offset = mask_tex_coord_offset_location(); - locations->alpha = alpha_location(); - locations->backdrop = backdrop_location(); - locations->backdrop_rect = backdrop_rect_location(); - if (mask_for_background()) - locations->original_backdrop = original_backdrop_location(); -} - -FragmentShaderRGBATexAlphaMaskAA::FragmentShaderRGBATexAlphaMaskAA() - : sampler_location_(-1), - mask_sampler_location_(-1), - alpha_location_(-1), - mask_tex_coord_scale_location_(-1), - mask_tex_coord_offset_location_(-1) { -} - -void FragmentShaderRGBATexAlphaMaskAA::Init(GLES2Interface* context, - unsigned program, - int* base_uniform_index) { - static const char* uniforms[] = { - "s_texture", - "s_mask", - "alpha", - "maskTexCoordScale", - "maskTexCoordOffset", - BLEND_MODE_UNIFORMS, - }; - int locations[arraysize(uniforms)]; - - GetProgramUniformLocations(context, - program, - arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS, - uniforms, - locations, - base_uniform_index); - sampler_location_ = locations[0]; - mask_sampler_location_ = locations[1]; - alpha_location_ = locations[2]; - mask_tex_coord_scale_location_ = locations[3]; - mask_tex_coord_offset_location_ = locations[4]; - BLEND_MODE_SET_LOCATIONS(locations, 5); -} - std::string FragmentShaderRGBATexAlphaMaskAA::GetShaderSource() const { return SHADER0([]() { precision mediump float; @@ -1572,61 +1400,6 @@ }); } -void FragmentShaderRGBATexAlphaMaskAA::FillLocations( - ShaderLocations* locations) const { - locations->sampler = sampler_location(); - locations->mask_sampler = mask_sampler_location(); - locations->mask_tex_coord_scale = mask_tex_coord_scale_location(); - locations->mask_tex_coord_offset = mask_tex_coord_offset_location(); - locations->alpha = alpha_location(); - locations->backdrop = backdrop_location(); - locations->backdrop_rect = backdrop_rect_location(); - if (mask_for_background()) - locations->original_backdrop = original_backdrop_location(); -} - -FragmentShaderRGBATexAlphaMaskColorMatrixAA:: - FragmentShaderRGBATexAlphaMaskColorMatrixAA() - : sampler_location_(-1), - mask_sampler_location_(-1), - alpha_location_(-1), - mask_tex_coord_scale_location_(-1), - color_matrix_location_(-1), - color_offset_location_(-1) { -} - -void FragmentShaderRGBATexAlphaMaskColorMatrixAA::Init( - GLES2Interface* context, - unsigned program, - int* base_uniform_index) { - static const char* uniforms[] = { - "s_texture", - "s_mask", - "alpha", - "maskTexCoordScale", - "maskTexCoordOffset", - "colorMatrix", - "colorOffset", - BLEND_MODE_UNIFORMS, - }; - int locations[arraysize(uniforms)]; - - GetProgramUniformLocations(context, - program, - arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS, - uniforms, - locations, - base_uniform_index); - sampler_location_ = locations[0]; - mask_sampler_location_ = locations[1]; - alpha_location_ = locations[2]; - mask_tex_coord_scale_location_ = locations[3]; - mask_tex_coord_offset_location_ = locations[4]; - color_matrix_location_ = locations[5]; - color_offset_location_ = locations[6]; - BLEND_MODE_SET_LOCATIONS(locations, 7); -} - std::string FragmentShaderRGBATexAlphaMaskColorMatrixAA::GetShaderSource() const { return SHADER0([]() { @@ -1660,50 +1433,6 @@ }); } -void FragmentShaderRGBATexAlphaMaskColorMatrixAA::FillLocations( - ShaderLocations* locations) const { - locations->sampler = sampler_location(); - locations->alpha = alpha_location(); - locations->mask_sampler = mask_sampler_location(); - locations->mask_tex_coord_scale = mask_tex_coord_scale_location(); - locations->mask_tex_coord_offset = mask_tex_coord_offset_location(); - locations->color_matrix = color_matrix_location(); - locations->color_offset = color_offset_location(); - locations->backdrop = backdrop_location(); - locations->backdrop_rect = backdrop_rect_location(); - if (mask_for_background()) - locations->original_backdrop = original_backdrop_location(); -} - -FragmentShaderRGBATexAlphaColorMatrixAA:: - FragmentShaderRGBATexAlphaColorMatrixAA() - : sampler_location_(-1), - alpha_location_(-1), - color_matrix_location_(-1), - color_offset_location_(-1) { -} - -void FragmentShaderRGBATexAlphaColorMatrixAA::Init(GLES2Interface* context, - unsigned program, - int* base_uniform_index) { - static const char* uniforms[] = { - "s_texture", "alpha", "colorMatrix", "colorOffset", BLEND_MODE_UNIFORMS, - }; - int locations[arraysize(uniforms)]; - - GetProgramUniformLocations(context, - program, - arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS, - uniforms, - locations, - base_uniform_index); - sampler_location_ = locations[0]; - alpha_location_ = locations[1]; - color_matrix_location_ = locations[2]; - color_offset_location_ = locations[3]; - BLEND_MODE_SET_LOCATIONS(locations, 4); -} - std::string FragmentShaderRGBATexAlphaColorMatrixAA::GetShaderSource() const { return SHADER0([]() { precision mediump float; @@ -1728,55 +1457,6 @@ }); } -void FragmentShaderRGBATexAlphaColorMatrixAA::FillLocations( - ShaderLocations* locations) const { - locations->sampler = sampler_location(); - locations->alpha = alpha_location(); - locations->color_matrix = color_matrix_location(); - locations->color_offset = color_offset_location(); - locations->backdrop = backdrop_location(); - locations->backdrop_rect = backdrop_rect_location(); -} - -FragmentShaderRGBATexAlphaMaskColorMatrix:: - FragmentShaderRGBATexAlphaMaskColorMatrix() - : sampler_location_(-1), - mask_sampler_location_(-1), - alpha_location_(-1), - mask_tex_coord_scale_location_(-1) { -} - -void FragmentShaderRGBATexAlphaMaskColorMatrix::Init(GLES2Interface* context, - unsigned program, - int* base_uniform_index) { - static const char* uniforms[] = { - "s_texture", - "s_mask", - "alpha", - "maskTexCoordScale", - "maskTexCoordOffset", - "colorMatrix", - "colorOffset", - BLEND_MODE_UNIFORMS, - }; - int locations[arraysize(uniforms)]; - - GetProgramUniformLocations(context, - program, - arraysize(uniforms) - UNUSED_BLEND_MODE_UNIFORMS, - uniforms, - locations, - base_uniform_index); - sampler_location_ = locations[0]; - mask_sampler_location_ = locations[1]; - alpha_location_ = locations[2]; - mask_tex_coord_scale_location_ = locations[3]; - mask_tex_coord_offset_location_ = locations[4]; - color_matrix_location_ = locations[5]; - color_offset_location_ = locations[6]; - BLEND_MODE_SET_LOCATIONS(locations, 7); -} - std::string FragmentShaderRGBATexAlphaMaskColorMatrix::GetShaderSource() const { return SHADER0([]() { precision mediump float; @@ -1805,21 +1485,6 @@ }); } -void FragmentShaderRGBATexAlphaMaskColorMatrix::FillLocations( - ShaderLocations* locations) const { - locations->sampler = sampler_location(); - locations->mask_sampler = mask_sampler_location(); - locations->mask_tex_coord_scale = mask_tex_coord_scale_location(); - locations->mask_tex_coord_offset = mask_tex_coord_offset_location(); - locations->alpha = alpha_location(); - locations->color_matrix = color_matrix_location(); - locations->color_offset = color_offset_location(); - locations->backdrop = backdrop_location(); - locations->backdrop_rect = backdrop_rect_location(); - if (mask_for_background()) - locations->original_backdrop = original_backdrop_location(); -} - FragmentShaderYUVVideo::FragmentShaderYUVVideo() : y_texture_location_(-1), u_texture_location_(-1), @@ -1982,26 +1647,6 @@ return head + functions; } -FragmentShaderColor::FragmentShaderColor() : color_location_(-1) { -} - -void FragmentShaderColor::Init(GLES2Interface* context, - unsigned program, - int* base_uniform_index) { - static const char* uniforms[] = { - "color", - }; - int locations[arraysize(uniforms)]; - - GetProgramUniformLocations(context, - program, - arraysize(uniforms), - uniforms, - locations, - base_uniform_index); - color_location_ = locations[0]; -} - std::string FragmentShaderColor::GetShaderSource() const { return SHADER0([]() { precision mediump float; @@ -2010,26 +1655,6 @@ }); } -FragmentShaderColorAA::FragmentShaderColorAA() : color_location_(-1) { -} - -void FragmentShaderColorAA::Init(GLES2Interface* context, - unsigned program, - int* base_uniform_index) { - static const char* uniforms[] = { - "color", - }; - int locations[arraysize(uniforms)]; - - GetProgramUniformLocations(context, - program, - arraysize(uniforms), - uniforms, - locations, - base_uniform_index); - color_location_ = locations[0]; -} - std::string FragmentShaderColorAA::GetShaderSource() const { return SHADER0([]() { precision mediump float;
diff --git a/cc/output/shader.h b/cc/output/shader.h index fdccb593..a74a58f 100644 --- a/cc/output/shader.h +++ b/cc/output/shader.h
@@ -356,12 +356,12 @@ class FragmentShaderBase { public: + virtual void Init(gpu::gles2::GLES2Interface* context, + unsigned program, + int* base_uniform_index); std::string GetShaderString(TexCoordPrecision precision, SamplerType sampler) const; - - int backdrop_location() const { return backdrop_location_; } - int original_backdrop_location() const { return original_backdrop_location_; } - int backdrop_rect_location() const { return backdrop_rect_location_; } + void FillLocations(ShaderLocations* locations) const; BlendMode blend_mode() const { return blend_mode_; } void set_blend_mode(BlendMode blend_mode) { blend_mode_ = blend_mode; } @@ -371,19 +371,52 @@ } bool mask_for_background() const { return mask_for_background_; } + int sampler_location() const { return sampler_location_; } + int alpha_location() const { return alpha_location_; } + int color_location() const { return color_location_; } + int background_color_location() const { return background_color_location_; } + int fragment_tex_transform_location() const { + return fragment_tex_transform_location_; + } + protected: FragmentShaderBase(); virtual std::string GetShaderSource() const = 0; std::string SetBlendModeFunctions(const std::string& shader_string) const; - int backdrop_location_; - int original_backdrop_location_; - int backdrop_rect_location_; + // Used only if |blend_mode_| is not BLEND_MODE_NONE. + int backdrop_location_ = -1; + int original_backdrop_location_ = -1; + int backdrop_rect_location_ = -1; + + bool has_mask_sampler_ = false; + int mask_sampler_location_ = -1; + int mask_tex_coord_scale_location_ = -1; + int mask_tex_coord_offset_location_ = -1; + + bool has_color_matrix_ = false; + int color_matrix_location_ = -1; + int color_offset_location_ = -1; + + bool has_sampler_ = false; + int sampler_location_ = -1; + + bool has_uniform_alpha_ = false; + int alpha_location_ = -1; + + bool has_background_color_ = false; + int background_color_location_ = -1; + + bool has_fragment_tex_transform_ = false; + int fragment_tex_transform_location_ = -1; + + bool has_uniform_color_ = false; + int color_location_ = -1; private: - BlendMode blend_mode_; - bool mask_for_background_; + BlendMode blend_mode_ = BLEND_MODE_NONE; + bool mask_for_background_ = false; std::string GetHelperFunctions() const; std::string GetBlendFunction() const; @@ -392,74 +425,42 @@ class FragmentTexAlphaBinding : public FragmentShaderBase { public: - FragmentTexAlphaBinding(); - - void Init(gpu::gles2::GLES2Interface* context, - unsigned program, - int* base_uniform_index); - int alpha_location() const { return alpha_location_; } - int fragment_tex_transform_location() const { return -1; } - int sampler_location() const { return sampler_location_; } + FragmentTexAlphaBinding() { + has_sampler_ = true; + has_uniform_alpha_ = true; + } private: - int sampler_location_; - int alpha_location_; - DISALLOW_COPY_AND_ASSIGN(FragmentTexAlphaBinding); }; class FragmentTexColorMatrixAlphaBinding : public FragmentShaderBase { public: - FragmentTexColorMatrixAlphaBinding(); - - void Init(gpu::gles2::GLES2Interface* context, - unsigned program, - int* base_uniform_index); - int alpha_location() const { return alpha_location_; } - int color_matrix_location() const { return color_matrix_location_; } - int color_offset_location() const { return color_offset_location_; } - int fragment_tex_transform_location() const { return -1; } - int sampler_location() const { return sampler_location_; } + FragmentTexColorMatrixAlphaBinding() { + has_sampler_ = true; + has_uniform_alpha_ = true; + has_color_matrix_ = true; + } private: - int sampler_location_; - int alpha_location_; - int color_matrix_location_; - int color_offset_location_; }; class FragmentTexOpaqueBinding : public FragmentShaderBase { public: - FragmentTexOpaqueBinding(); - - void Init(gpu::gles2::GLES2Interface* context, - unsigned program, - int* base_uniform_index); - int alpha_location() const { return -1; } - int fragment_tex_transform_location() const { return -1; } - int background_color_location() const { return -1; } - int sampler_location() const { return sampler_location_; } + FragmentTexOpaqueBinding() { has_sampler_ = true; } private: - int sampler_location_; - DISALLOW_COPY_AND_ASSIGN(FragmentTexOpaqueBinding); }; class FragmentTexBackgroundBinding : public FragmentShaderBase { public: - FragmentTexBackgroundBinding(); - - void Init(gpu::gles2::GLES2Interface* context, - unsigned program, - int* base_uniform_index); - int background_color_location() const { return background_color_location_; } - int sampler_location() const { return sampler_location_; } + FragmentTexBackgroundBinding() { + has_sampler_ = true; + has_background_color_ = true; + } private: - int background_color_location_; - int sampler_location_; - DISALLOW_COPY_AND_ASSIGN(FragmentTexBackgroundBinding); }; @@ -486,18 +487,12 @@ }; class FragmentShaderRGBATexAlpha : public FragmentTexAlphaBinding { - public: - void FillLocations(ShaderLocations* locations) const; - private: std::string GetShaderSource() const override; }; class FragmentShaderRGBATexColorMatrixAlpha : public FragmentTexColorMatrixAlphaBinding { - public: - void FillLocations(ShaderLocations* locations) const; - private: std::string GetShaderSource() const override; }; @@ -526,42 +521,24 @@ class FragmentShaderRGBATexAlphaAA : public FragmentShaderBase { public: - FragmentShaderRGBATexAlphaAA(); - - void Init(gpu::gles2::GLES2Interface* context, - unsigned program, - int* base_uniform_index); - void FillLocations(ShaderLocations* locations) const; - - int alpha_location() const { return alpha_location_; } - int sampler_location() const { return sampler_location_; } + FragmentShaderRGBATexAlphaAA() { + has_sampler_ = true; + has_uniform_alpha_ = true; + } private: std::string GetShaderSource() const override; - int sampler_location_; - int alpha_location_; - DISALLOW_COPY_AND_ASSIGN(FragmentShaderRGBATexAlphaAA); }; class FragmentTexClampAlphaAABinding : public FragmentShaderBase { public: - FragmentTexClampAlphaAABinding(); - - void Init(gpu::gles2::GLES2Interface* context, - unsigned program, - int* base_uniform_index); - int alpha_location() const { return alpha_location_; } - int sampler_location() const { return sampler_location_; } - int fragment_tex_transform_location() const { - return fragment_tex_transform_location_; + FragmentTexClampAlphaAABinding() { + has_sampler_ = true; + has_uniform_alpha_ = true; + has_fragment_tex_transform_ = true; } - private: - int sampler_location_; - int alpha_location_; - int fragment_tex_transform_location_; - DISALLOW_COPY_AND_ASSIGN(FragmentTexClampAlphaAABinding); }; @@ -580,138 +557,62 @@ class FragmentShaderRGBATexAlphaMask : public FragmentShaderBase { public: - FragmentShaderRGBATexAlphaMask(); - void FillLocations(ShaderLocations* locations) const; - void Init(gpu::gles2::GLES2Interface* context, - unsigned program, - int* base_uniform_index); - int alpha_location() const { return alpha_location_; } - int sampler_location() const { return sampler_location_; } - int mask_sampler_location() const { return mask_sampler_location_; } - int mask_tex_coord_scale_location() const { - return mask_tex_coord_scale_location_; + FragmentShaderRGBATexAlphaMask() { + has_sampler_ = true; + has_uniform_alpha_ = true; + has_mask_sampler_ = true; } - int mask_tex_coord_offset_location() const { - return mask_tex_coord_offset_location_; - } - private: std::string GetShaderSource() const override; - int sampler_location_; - int mask_sampler_location_; - int alpha_location_; - int mask_tex_coord_scale_location_; - int mask_tex_coord_offset_location_; - DISALLOW_COPY_AND_ASSIGN(FragmentShaderRGBATexAlphaMask); }; class FragmentShaderRGBATexAlphaMaskAA : public FragmentShaderBase { public: - FragmentShaderRGBATexAlphaMaskAA(); - void FillLocations(ShaderLocations* locations) const; - void Init(gpu::gles2::GLES2Interface* context, - unsigned program, - int* base_uniform_index); - int alpha_location() const { return alpha_location_; } - int sampler_location() const { return sampler_location_; } - int mask_sampler_location() const { return mask_sampler_location_; } - int mask_tex_coord_scale_location() const { - return mask_tex_coord_scale_location_; + FragmentShaderRGBATexAlphaMaskAA() { + has_sampler_ = true; + has_uniform_alpha_ = true; + has_mask_sampler_ = true; } - int mask_tex_coord_offset_location() const { - return mask_tex_coord_offset_location_; - } - private: std::string GetShaderSource() const override; - int sampler_location_; - int mask_sampler_location_; - int alpha_location_; - int mask_tex_coord_scale_location_; - int mask_tex_coord_offset_location_; - DISALLOW_COPY_AND_ASSIGN(FragmentShaderRGBATexAlphaMaskAA); }; class FragmentShaderRGBATexAlphaMaskColorMatrixAA : public FragmentShaderBase { public: - FragmentShaderRGBATexAlphaMaskColorMatrixAA(); - void FillLocations(ShaderLocations* locations) const; - void Init(gpu::gles2::GLES2Interface* context, - unsigned program, - int* base_uniform_index); - int alpha_location() const { return alpha_location_; } - int sampler_location() const { return sampler_location_; } - int mask_sampler_location() const { return mask_sampler_location_; } - int mask_tex_coord_scale_location() const { - return mask_tex_coord_scale_location_; + FragmentShaderRGBATexAlphaMaskColorMatrixAA() { + has_sampler_ = true; + has_uniform_alpha_ = true; + has_mask_sampler_ = true; + has_color_matrix_ = true; } - int mask_tex_coord_offset_location() const { - return mask_tex_coord_offset_location_; - } - int color_matrix_location() const { return color_matrix_location_; } - int color_offset_location() const { return color_offset_location_; } - private: std::string GetShaderSource() const override; - int sampler_location_; - int mask_sampler_location_; - int alpha_location_; - int mask_tex_coord_scale_location_; - int mask_tex_coord_offset_location_; - int color_matrix_location_; - int color_offset_location_; }; class FragmentShaderRGBATexAlphaColorMatrixAA : public FragmentShaderBase { public: - FragmentShaderRGBATexAlphaColorMatrixAA(); - void FillLocations(ShaderLocations* locations) const; - void Init(gpu::gles2::GLES2Interface* context, - unsigned program, - int* base_uniform_index); - int alpha_location() const { return alpha_location_; } - int sampler_location() const { return sampler_location_; } - int color_matrix_location() const { return color_matrix_location_; } - int color_offset_location() const { return color_offset_location_; } + FragmentShaderRGBATexAlphaColorMatrixAA() { + has_sampler_ = true; + has_uniform_alpha_ = true; + has_color_matrix_ = true; + } private: std::string GetShaderSource() const override; - int sampler_location_; - int alpha_location_; - int color_matrix_location_; - int color_offset_location_; }; class FragmentShaderRGBATexAlphaMaskColorMatrix : public FragmentShaderBase { public: - FragmentShaderRGBATexAlphaMaskColorMatrix(); - void FillLocations(ShaderLocations* locations) const; - void Init(gpu::gles2::GLES2Interface* context, - unsigned program, - int* base_uniform_index); - int alpha_location() const { return alpha_location_; } - int sampler_location() const { return sampler_location_; } - int mask_sampler_location() const { return mask_sampler_location_; } - int mask_tex_coord_scale_location() const { - return mask_tex_coord_scale_location_; + FragmentShaderRGBATexAlphaMaskColorMatrix() { + has_sampler_ = true; + has_uniform_alpha_ = true; + has_mask_sampler_ = true; + has_color_matrix_ = true; } - int mask_tex_coord_offset_location() const { - return mask_tex_coord_offset_location_; - } - int color_matrix_location() const { return color_matrix_location_; } - int color_offset_location() const { return color_offset_location_; } - private: std::string GetShaderSource() const override; - int sampler_location_; - int mask_sampler_location_; - int alpha_location_; - int mask_tex_coord_scale_location_; - int mask_tex_coord_offset_location_; - int color_matrix_location_; - int color_offset_location_; }; class FragmentShaderYUVVideo : public FragmentShaderBase { @@ -721,7 +622,7 @@ void Init(gpu::gles2::GLES2Interface* context, unsigned program, - int* base_uniform_index); + int* base_uniform_index) override; int y_texture_location() const { return y_texture_location_; } int u_texture_location() const { return u_texture_location_; } int v_texture_location() const { return v_texture_location_; } @@ -741,56 +642,42 @@ private: std::string GetShaderSource() const override; - bool use_alpha_texture_; - bool use_nv12_; - bool use_color_lut_; + bool use_alpha_texture_ = false; + bool use_nv12_ = false; + bool use_color_lut_ = false; - int y_texture_location_; - int u_texture_location_; - int v_texture_location_; - int uv_texture_location_; - int a_texture_location_; - int lut_texture_location_; - int alpha_location_; - int yuv_matrix_location_; - int yuv_adj_location_; - int ya_clamp_rect_location_; - int uv_clamp_rect_location_; - int resource_multiplier_location_; - int resource_offset_location_; + int y_texture_location_ = -1; + int u_texture_location_ = -1; + int v_texture_location_ = -1; + int uv_texture_location_ = -1; + int a_texture_location_ = -1; + int lut_texture_location_ = -1; + int alpha_location_ = -1; + int yuv_matrix_location_ = -1; + int yuv_adj_location_ = -1; + int ya_clamp_rect_location_ = -1; + int uv_clamp_rect_location_ = -1; + int resource_multiplier_location_ = -1; + int resource_offset_location_ = -1; DISALLOW_COPY_AND_ASSIGN(FragmentShaderYUVVideo); }; class FragmentShaderColor : public FragmentShaderBase { public: - FragmentShaderColor(); - - void Init(gpu::gles2::GLES2Interface* context, - unsigned program, - int* base_uniform_index); - int color_location() const { return color_location_; } + FragmentShaderColor() { has_uniform_color_ = true; } private: std::string GetShaderSource() const override; - int color_location_; - DISALLOW_COPY_AND_ASSIGN(FragmentShaderColor); }; class FragmentShaderColorAA : public FragmentShaderBase { public: - FragmentShaderColorAA(); - - void Init(gpu::gles2::GLES2Interface* context, - unsigned program, - int* base_uniform_index); - int color_location() const { return color_location_; } + FragmentShaderColorAA() { has_uniform_color_ = true; } private: std::string GetShaderSource() const override; - int color_location_; - DISALLOW_COPY_AND_ASSIGN(FragmentShaderColorAA); };
diff --git a/chrome/android/java/res/layout/download_item_view.xml b/chrome/android/java/res/layout/download_item_view.xml index 1210f0f4..9d70beaa 100644 --- a/chrome/android/java/res/layout/download_item_view.xml +++ b/chrome/android/java/res/layout/download_item_view.xml
@@ -88,10 +88,11 @@ <TextView android:id="@+id/filename_progress_view" android:layout_width="wrap_content" - android:layout_height="18dp" + android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentStart="true" android:layout_toStartOf="@+id/pause_button" + android:minHeight="18dp" android:singleLine="true" android:textColor="@color/default_text_color" android:textSize="14sp" /> @@ -112,13 +113,14 @@ <TextView android:id="@+id/status_view" android:layout_width="wrap_content" - android:layout_height="18dp" + android:layout_height="wrap_content" android:layout_marginEnd="16dp" android:layout_marginTop="0dp" android:layout_alignParentBottom="true" android:layout_alignParentStart="true" android:layout_toStartOf="@+id/pause_button" android:layout_below="@+id/download_progress_view" + android:minHeight="18dp" android:textAlignment="viewStart" android:textColor="@color/google_grey_600" android:textSize="12sp"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java index f4a3c9e..437c88d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java
@@ -318,10 +318,8 @@ */ @CalledByNative private void onDownloadStarted(String filename) { - if (!isDangerousFile(filename)) { - DownloadUtils.showDownloadStartToast(mContext); - closeBlankTab(); - } + DownloadUtils.showDownloadStartToast(mContext); + closeBlankTab(); } /** @@ -378,16 +376,6 @@ } /** - * Check whether a file is dangerous. - * - * @param filename Name of the file. - * @return true if the file is dangerous, or false otherwise. - */ - protected boolean isDangerousFile(String filename) { - return nativeIsDownloadDangerous(filename); - } - - /** * Discards a downloaded file. * * @param filepath File to be discarded. @@ -475,7 +463,6 @@ private native void nativeInit(WebContents webContents); private static native String nativeGetDownloadWarningText(String filename); - private static native boolean nativeIsDownloadDangerous(String filename); private static native void nativeLaunchDuplicateDownloadInfoBar(ChromeDownloadDelegate delegate, Tab tab, DownloadInfo downloadInfo, String filePath, boolean isIncognito); private static native void nativeLaunchPermissionUpdateInfoBar(
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index cc98c5c..c2e46f6 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -1067,8 +1067,8 @@ <message name="IDS_SETTINGS_INTERNET_NETWORK_SECTION_EXPAND_ACCESSIBILITY_LABEL" desc="Label for the button that toggles showing the advanced network options. Only visible by screen reader software."> Show advanced network options </message> - <message name="IDS_SETTINGS_INTERNET_NETWORK_SECTION_NAMESERVERS" desc="Settings > Internet > Network details: Nameservers section label."> - Nameservers + <message name="IDS_SETTINGS_INTERNET_NETWORK_SECTION_NAMESERVERS" desc="Settings > Internet > Network details: Name servers section label."> + Name servers </message> <message name="IDS_SETTINGS_INTERNET_NETWORK_SECTION_NETWORK" desc="Settings > Internet > Network details: Network section label."> Network @@ -2123,8 +2123,11 @@ <message name="IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_WEAK_PIN" desc="Message shown below the title that warns the user they have entered a PIN that is easy to guess."> PIN may be easy to guess </message> - <message name="IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_TOO_SHORT" desc="Message shown below the title that tells the user that the PIN they entered needs to be at least four digits long."> - PIN must be at least 4 digits + <message name="IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_TOO_SHORT" desc="Message shown below the title that tells the user that the PIN they entered needs to be at least minimum digits long."> + PIN must be at least <ph name="MINIMUM">$1<ex>4</ex></ph> digits + </message> + <message name="IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_TOO_LONG" desc="Message shown below the title that tells the user that the PIN they entered needs to be less than maximum digits long."> + PIN must be less than <ph name="MAXIMUM">$1<ex>0</ex></ph> digits </message> <message name="IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_MISMATCHED" desc="Message shown below the title that tells the user they have entered two different PIN values."> PINs do not match
diff --git a/chrome/browser/android/download/chrome_download_delegate.cc b/chrome/browser/android/download/chrome_download_delegate.cc index a9eb13f..0bbb8362 100644 --- a/chrome/browser/android/download/chrome_download_delegate.cc +++ b/chrome/browser/android/download/chrome_download_delegate.cc
@@ -42,15 +42,6 @@ base::android::ConvertJavaStringToUTF16(env, filename))); } -// Returns true if a file name is dangerous, or false otherwise. -static jboolean IsDownloadDangerous(JNIEnv* env, - const JavaParamRef<jclass>& clazz, - const JavaParamRef<jstring>& filename) { - base::FilePath path(base::android::ConvertJavaStringToUTF8(env, filename)); - return safe_browsing::FileTypePolicies::GetInstance()->GetFileDangerLevel( - path) != safe_browsing::DownloadFileType::NOT_DANGEROUS; -} - // static bool ChromeDownloadDelegate::EnqueueDownloadManagerRequest( jobject chrome_download_delegate,
diff --git a/chrome/browser/android/download/download_controller.cc b/chrome/browser/android/download/download_controller.cc index 908b121..c77b0f28 100644 --- a/chrome/browser/android/download/download_controller.cc +++ b/chrome/browser/android/download/download_controller.cc
@@ -243,7 +243,9 @@ ChromeDownloadDelegate* delegate = ChromeDownloadDelegate::FromWebContents(web_contents); - if (delegate) { + // For dangerous item, we need to show the dangerous infobar before the + // download can start. + if (!download_item->IsDangerous() && delegate) { delegate->OnDownloadStarted( download_item->GetTargetFilePath().BaseName().value()); }
diff --git a/chrome/browser/android/offline_pages/offline_page_mhtml_archiver.cc b/chrome/browser/android/offline_pages/offline_page_mhtml_archiver.cc index 0600f24a..e897f06 100644 --- a/chrome/browser/android/offline_pages/offline_page_mhtml_archiver.cc +++ b/chrome/browser/android/offline_pages/offline_page_mhtml_archiver.cc
@@ -8,12 +8,10 @@ #include "base/bind_helpers.h" #include "base/files/file_path.h" #include "base/files/file_util.h" +#include "base/guid.h" #include "base/location.h" #include "base/logging.h" #include "base/strings/string16.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/ssl/security_state_tab_helper.h" #include "components/security_state/core/security_state.h" @@ -25,13 +23,6 @@ namespace offline_pages { namespace { const base::FilePath::CharType kMHTMLExtension[] = FILE_PATH_LITERAL("mhtml"); -const base::FilePath::CharType kDefaultFileName[] = - FILE_PATH_LITERAL("offline_page"); -const int kTitleLengthMax = 80; -const char kMHTMLFileNameExtension[] = ".mhtml"; -const char kFileNameComponentsSeparator[] = "-"; -const char kReplaceChars[] = " "; -const char kReplaceWith[] = "_"; void DeleteFileOnFileThread(const base::FilePath& file_path, const base::Closure& callback) { @@ -44,34 +35,6 @@ } // namespace // static -std::string OfflinePageMHTMLArchiver::GetFileNameExtension() { - return kMHTMLFileNameExtension; -} - -// static -base::FilePath OfflinePageMHTMLArchiver::GenerateFileName( - const GURL& url, - const std::string& title, - int64_t archive_id) { - std::string title_part(title.substr(0, kTitleLengthMax)); - std::string suggested_name( - url.host() + kFileNameComponentsSeparator + - title_part + kFileNameComponentsSeparator + - base::Int64ToString(archive_id)); - - // Substitute spaces out from title. - base::ReplaceChars(suggested_name, kReplaceChars, kReplaceWith, - &suggested_name); - - return net::GenerateFileName(url, - std::string(), // content disposition - std::string(), // charset - suggested_name, - std::string(), // mime-type - kDefaultFileName) - .AddExtension(kMHTMLExtension); -} - OfflinePageMHTMLArchiver::OfflinePageMHTMLArchiver( content::WebContents* web_contents) : web_contents_(web_contents), @@ -129,9 +92,7 @@ GURL url(web_contents_->GetLastCommittedURL()); base::string16 title(web_contents_->GetTitle()); base::FilePath file_path( - archives_dir.Append( - GenerateFileName(url, base::UTF16ToUTF8(title), archive_id))); - + archives_dir.Append(base::GenerateGUID()).AddExtension(kMHTMLExtension)); content::MHTMLGenerationParams params(file_path); params.use_binary_encoding = true;
diff --git a/chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h b/chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h index 9dedbdd..e1c78430 100644 --- a/chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h +++ b/chrome/browser/android/offline_pages/offline_page_mhtml_archiver.h
@@ -42,13 +42,6 @@ // } class OfflinePageMHTMLArchiver : public OfflinePageArchiver { public: - // Returns the extension name of the offline page file. - static std::string GetFileNameExtension(); - // Creates a file name for the archive file based on url and title. Public for - // testing. - static base::FilePath GenerateFileName(const GURL& url, - const std::string& title, - int64_t archive_id); explicit OfflinePageMHTMLArchiver(content::WebContents* web_contents); ~OfflinePageMHTMLArchiver() override;
diff --git a/chrome/browser/android/offline_pages/offline_page_mhtml_archiver_unittest.cc b/chrome/browser/android/offline_pages/offline_page_mhtml_archiver_unittest.cc index b6539b51..72845ca 100644 --- a/chrome/browser/android/offline_pages/offline_page_mhtml_archiver_unittest.cc +++ b/chrome/browser/android/offline_pages/offline_page_mhtml_archiver_unittest.cc
@@ -233,37 +233,4 @@ EXPECT_EQ(kTestFileSize, last_file_size()); } -TEST_F(OfflinePageMHTMLArchiverTest, GenerateFileName) { - GURL url_1("http://news.google.com/page1"); - std::string title_1("Google News Page"); - base::FilePath expected_1(FILE_PATH_LITERAL( - "news.google.com-Google_News_Page-1234.mhtml")); - base::FilePath actual_1( - OfflinePageMHTMLArchiver::GenerateFileName(url_1, title_1, 1234LL)); - EXPECT_EQ(expected_1, actual_1); - - GURL url_2("https://en.m.wikipedia.org/Sample_page_about_stuff"); - std::string title_2("Some Wiki Page"); - base::FilePath expected_2(FILE_PATH_LITERAL( - "en.m.wikipedia.org-Some_Wiki_Page-56789.mhtml")); - base::FilePath actual_2( - OfflinePageMHTMLArchiver::GenerateFileName(url_2, title_2, 56789LL)); - EXPECT_EQ(expected_2, actual_2); - - GURL url_3("https://www.google.com/search"); - std::string title_3 = - "A really really really really really long title " - "that is over 80 chars long here^ - TRUNCATE THIS PART"; - std::string expected_title_3_part = - "A_really_really_really_really_really_long_title_" - "that_is_over_80_chars_long_here^"; - base::FilePath expected_3( - FILE_PATH_LITERAL("www.google.com-" + - expected_title_3_part + - "-123456789.mhtml")); - base::FilePath actual_3( - OfflinePageMHTMLArchiver::GenerateFileName(url_3, title_3, 123456789LL)); - EXPECT_EQ(expected_3, actual_3); -} - } // namespace offline_pages
diff --git a/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc b/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc index 4c2841a8..332add5 100644 --- a/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc
@@ -514,6 +514,7 @@ }; class WebViewNewWindowInteractiveTest : public WebViewInteractiveTest {}; +class WebViewPointerLockInteractiveTest : public WebViewInteractiveTest {}; // The tests below aren't needed in --use-cross-process-frames-for-guests. class WebViewContextMenuInteractiveTest : public WebViewInteractiveTestBase {}; @@ -523,7 +524,6 @@ // with WebViewInteractiveTest (see crbug.com/582562). class WebViewFocusInteractiveTest : public WebViewInteractiveTestBase {}; class WebViewPopupInteractiveTest : public WebViewInteractiveTestBase {}; -class WebViewPointerLockInteractiveTest : public WebViewInteractiveTestBase {}; class WebViewDragDropInteractiveTest : public WebViewInteractiveTestBase {}; INSTANTIATE_TEST_CASE_P(WebViewInteractiveTests, @@ -534,6 +534,10 @@ WebViewNewWindowInteractiveTest, testing::Bool()); +INSTANTIATE_TEST_CASE_P(WebViewInteractiveTests, + WebViewPointerLockInteractiveTest, + testing::Bool()); + // ui_test_utils::SendMouseMoveSync doesn't seem to work on OS_MACOSX, and // likely won't work on many other platforms as well, so for now this test // is for Windows and Linux only. As of Sept 17th, 2013 this test is disabled @@ -544,7 +548,7 @@ #if defined(OS_LINUX) // flaky http://crbug.com/412086 -IN_PROC_BROWSER_TEST_F(WebViewPointerLockInteractiveTest, +IN_PROC_BROWSER_TEST_P(WebViewPointerLockInteractiveTest, DISABLED_PointerLock) { SetupTest("web_view/pointer_lock", "/extensions/platform_apps/web_view/pointer_lock/guest.html"); @@ -618,7 +622,7 @@ } // flaky http://crbug.com/412086 -IN_PROC_BROWSER_TEST_F(WebViewPointerLockInteractiveTest, +IN_PROC_BROWSER_TEST_P(WebViewPointerLockInteractiveTest, DISABLED_PointerLockFocus) { SetupTest("web_view/pointer_lock_focus", "/extensions/platform_apps/web_view/pointer_lock_focus/guest.html"); @@ -1106,7 +1110,7 @@ ASSERT_TRUE(done_listener.WaitUntilSatisfied()); } -IN_PROC_BROWSER_TEST_F(WebViewPointerLockInteractiveTest, +IN_PROC_BROWSER_TEST_P(WebViewPointerLockInteractiveTest, PointerLock_PointerLockLostWithFocus) { TestHelper("testPointerLockLostWithFocus", "web_view/pointerlock",
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc index 40f4f5c4..e4be8323 100644 --- a/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc +++ b/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc
@@ -311,12 +311,11 @@ EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); } -// Flaky: http://crbug.com/675851 // Tests that fullscreen transitions during a tab capture session dispatch // events to the onStatusChange listener. The test loads a page that toggles // fullscreen mode, using the Fullscreen Javascript API, in response to mouse // clicks. -IN_PROC_BROWSER_TEST_F(TabCaptureApiTest, DISABLED_FullscreenEvents) { +IN_PROC_BROWSER_TEST_F(TabCaptureApiTest, FullscreenEvents) { AddExtensionToCommandLineWhitelist(); ExtensionTestMessageListener capture_started("tab_capture_started", false);
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc index 757222b..f5acaf6 100644 --- a/chrome/browser/profiles/profile_io_data.cc +++ b/chrome/browser/profiles/profile_io_data.cc
@@ -1190,7 +1190,7 @@ #endif // !BUILDFLAG(DISABLE_FTP_SUPPORT) #if BUILDFLAG(DEBUG_DEVTOOLS) - request_interceptors.push_back(new DebugDevToolsInterceptor); + request_interceptors.push_back(base::MakeUnique<DebugDevToolsInterceptor>()); #endif // Set up interceptors in the reverse order.
diff --git a/chrome/browser/resources/hotword/always_on_manager.js b/chrome/browser/resources/hotword/always_on_manager.js index 042a8d2..f34bc6d 100644 --- a/chrome/browser/resources/hotword/always_on_manager.js +++ b/chrome/browser/resources/hotword/always_on_manager.js
@@ -14,18 +14,17 @@ * @extends {hotword.BaseSessionManager} */ function AlwaysOnManager(stateManager) { - hotword.BaseSessionManager.call(this, - stateManager, - hotword.constants.SessionSource.ALWAYS); + hotword.BaseSessionManager.call( + this, stateManager, hotword.constants.SessionSource.ALWAYS); } AlwaysOnManager.prototype = { __proto__: hotword.BaseSessionManager.prototype, /** @override */ - enabled: function() { - return this.stateManager.isAlwaysOnEnabled(); - }, + enabled: function() { + return this.stateManager.isAlwaysOnEnabled(); + }, /** @override */ updateListeners: function() { @@ -35,7 +34,5 @@ } }; - return { - AlwaysOnManager: AlwaysOnManager - }; + return {AlwaysOnManager: AlwaysOnManager}; });
diff --git a/chrome/browser/resources/hotword/audio_client.js b/chrome/browser/resources/hotword/audio_client.js index f74f84b..b3343b43 100644 --- a/chrome/browser/resources/hotword/audio_client.js +++ b/chrome/browser/resources/hotword/audio_client.js
@@ -133,8 +133,9 @@ */ AudioClient.prototype.checkSpeechOverlayUi_ = function() { if (!this.speechOverlay_) { - window.setTimeout(this.delayedCheckSpeechOverlayUi_.bind(this), - AudioClient.RETRY_TIME_MS_); + window.setTimeout( + this.delayedCheckSpeechOverlayUi_.bind(this), + AudioClient.RETRY_TIME_MS_); } else { this.checkSpeechUiRetries_ = 0; } @@ -147,8 +148,8 @@ * @private */ AudioClient.prototype.delayedCheckSpeechOverlayUi_ = function() { - this.speechOverlay_ = document.getElementById( - AudioClient.SPEECH_UI_OVERLAY_ID_); + this.speechOverlay_ = + document.getElementById(AudioClient.SPEECH_UI_OVERLAY_ID_); if (!this.speechOverlay_) { if (this.checkSpeechUiRetries_++ < AudioClient.MAX_RETRIES) { this.sendCommandToPage_(AudioClient.CommandToPage.VOICE_TRIGGER); @@ -167,9 +168,8 @@ * @private */ AudioClient.prototype.checkUi_ = function(command) { - this.uiStatus_[command].timeoutId = - window.setTimeout(this.failedCheckUi_.bind(this, command), - AudioClient.RETRY_TIME_MS_); + this.uiStatus_[command].timeoutId = window.setTimeout( + this.failedCheckUi_.bind(this, command), AudioClient.RETRY_TIME_MS_); }; /**
diff --git a/chrome/browser/resources/hotword/base_session_manager.js b/chrome/browser/resources/hotword/base_session_manager.js index d1ee2bf..6891199 100644 --- a/chrome/browser/resources/hotword/base_session_manager.js +++ b/chrome/browser/resources/hotword/base_session_manager.js
@@ -56,8 +56,7 @@ * Called when the hotwording session is stopped. * @protected */ - onSessionStop: function() { - }, + onSessionStop: function() {}, /** * Starts a launcher hotwording session. @@ -65,13 +64,9 @@ * recognizer in. */ startSession: function(opt_mode) { - this.stateManager.startSession( - this.sessionSource_, - function() { - chrome.hotwordPrivate.setHotwordSessionState(true, function() {}); - }, - this.handleHotwordTrigger.bind(this), - opt_mode); + this.stateManager.startSession(this.sessionSource_, function() { + chrome.hotwordPrivate.setHotwordSessionState(true, function() {}); + }, this.handleHotwordTrigger.bind(this), opt_mode); }, /** @@ -90,9 +85,8 @@ */ handleHotwordTrigger: function(log) { hotword.debug('Hotword triggered: ' + this.sessionSource_, log); - chrome.hotwordPrivate.notifyHotwordRecognition('search', - log, - function() {}); + chrome.hotwordPrivate.notifyHotwordRecognition( + 'search', log, function() {}); }, /** @@ -154,7 +148,5 @@ } }; - return { - BaseSessionManager: BaseSessionManager - }; + return {BaseSessionManager: BaseSessionManager}; });
diff --git a/chrome/browser/resources/hotword/constants.js b/chrome/browser/resources/hotword/constants.js index 988f9b8..0fbfa0e 100644 --- a/chrome/browser/resources/hotword/constants.js +++ b/chrome/browser/resources/hotword/constants.js
@@ -3,308 +3,297 @@ // found in the LICENSE file. cr.define('hotword.constants', function() { -'use strict'; + 'use strict'; -/** - * Number of seconds of audio to record when logging is enabled. - * @const {number} - */ -var AUDIO_LOG_SECONDS = 2; + /** + * Number of seconds of audio to record when logging is enabled. + * @const {number} + */ + var AUDIO_LOG_SECONDS = 2; -/** - * Timeout in seconds, for detecting false positives with a hotword stream. - * @const {number} - */ -var HOTWORD_STREAM_TIMEOUT_SECONDS = 2; + /** + * Timeout in seconds, for detecting false positives with a hotword stream. + * @const {number} + */ + var HOTWORD_STREAM_TIMEOUT_SECONDS = 2; -/** - * Hotword data shared module extension's ID. - * @const {string} - */ -var SHARED_MODULE_ID = 'lccekmodgklaepjeofjdjpbminllajkg'; + /** + * Hotword data shared module extension's ID. + * @const {string} + */ + var SHARED_MODULE_ID = 'lccekmodgklaepjeofjdjpbminllajkg'; -/** - * Path to shared module data. - * @const {string} - */ -var SHARED_MODULE_ROOT = '_modules/' + SHARED_MODULE_ID; + /** + * Path to shared module data. + * @const {string} + */ + var SHARED_MODULE_ROOT = '_modules/' + SHARED_MODULE_ID; -/** - * Name used by the content scripts to create communications Ports. - * @const {string} - */ -var CLIENT_PORT_NAME = 'chwcpn'; + /** + * Name used by the content scripts to create communications Ports. + * @const {string} + */ + var CLIENT_PORT_NAME = 'chwcpn'; -/** - * The field name to specify the command among pages. - * @const {string} - */ -var COMMAND_FIELD_NAME = 'cmd'; + /** + * The field name to specify the command among pages. + * @const {string} + */ + var COMMAND_FIELD_NAME = 'cmd'; -/** - * The speaker model file name. - * @const {string} - */ -var SPEAKER_MODEL_FILE_NAME = 'speaker_model.data'; + /** + * The speaker model file name. + * @const {string} + */ + var SPEAKER_MODEL_FILE_NAME = 'speaker_model.data'; -/** - * The training utterance file name prefix. - * @const {string} - */ -var UTTERANCE_FILE_PREFIX = 'utterance-'; + /** + * The training utterance file name prefix. + * @const {string} + */ + var UTTERANCE_FILE_PREFIX = 'utterance-'; -/** - * The training utterance file extension. - * @const {string} - */ -var UTTERANCE_FILE_EXTENSION = '.raw'; + /** + * The training utterance file extension. + * @const {string} + */ + var UTTERANCE_FILE_EXTENSION = '.raw'; -/** - * The number of training utterances required to train the speaker model. - * @const {number} - */ -var NUM_TRAINING_UTTERANCES = 3; + /** + * The number of training utterances required to train the speaker model. + * @const {number} + */ + var NUM_TRAINING_UTTERANCES = 3; -/** - * The size of the file system requested for reading the speaker model and - * utterances. This number should always be larger than the combined file size, - * currently 576338 bytes as of February 2015. - * @const {number} - */ -var FILE_SYSTEM_SIZE_BYTES = 1048576; + /** + * The size of the file system requested for reading the speaker model and + * utterances. This number should always be larger than the combined file + * size, + * currently 576338 bytes as of February 2015. + * @const {number} + */ + var FILE_SYSTEM_SIZE_BYTES = 1048576; -/** - * Time to wait for expected messages, in milliseconds. - * @enum {number} - */ -var TimeoutMs = { - SHORT: 200, - NORMAL: 500, - LONG: 2000 -}; + /** + * Time to wait for expected messages, in milliseconds. + * @enum {number} + */ + var TimeoutMs = {SHORT: 200, NORMAL: 500, LONG: 2000}; -/** - * The URL of the files used by the plugin. - * @enum {string} - */ -var File = { - RECOGNIZER_CONFIG: 'hotword.data', -}; + /** + * The URL of the files used by the plugin. + * @enum {string} + */ + var File = { + RECOGNIZER_CONFIG: 'hotword.data', + }; -/** - * Errors emitted by the NaClManager. - * @enum {string} - */ -var Error = { - NACL_CRASH: 'nacl_crash', - TIMEOUT: 'timeout', -}; + /** + * Errors emitted by the NaClManager. + * @enum {string} + */ + var Error = { + NACL_CRASH: 'nacl_crash', + TIMEOUT: 'timeout', + }; -/** - * Event types supported by NaClManager. - * @enum {string} - */ -var Event = { - READY: 'ready', - TRIGGER: 'trigger', - SPEAKER_MODEL_SAVED: 'speaker model saved', - ERROR: 'error', - TIMEOUT: 'timeout', -}; + /** + * Event types supported by NaClManager. + * @enum {string} + */ + var Event = { + READY: 'ready', + TRIGGER: 'trigger', + SPEAKER_MODEL_SAVED: 'speaker model saved', + ERROR: 'error', + TIMEOUT: 'timeout', + }; -/** - * Messages for communicating with the NaCl recognizer plugin. These must match - * constants in <google3>/hotword_plugin.c - * @enum {string} - */ -var NaClPlugin = { - RESTART: 'r', - SAMPLE_RATE_PREFIX: 'h', - MODEL_PREFIX: 'm', - STOP: 's', - LOG: 'l', - DSP: 'd', - BEGIN_SPEAKER_MODEL: 'b', - ADAPT_SPEAKER_MODEL: 'a', - FINISH_SPEAKER_MODEL: 'f', - SPEAKER_MODEL_SAVED: 'sm_saved', - REQUEST_MODEL: 'model', - MODEL_LOADED: 'model_loaded', - READY_FOR_AUDIO: 'audio', - STOPPED: 'stopped', - HOTWORD_DETECTED: 'hotword', - MS_CONFIGURED: 'ms_configured', - TIMEOUT: 'timeout' -}; + /** + * Messages for communicating with the NaCl recognizer plugin. These must + * match + * constants in <google3>/hotword_plugin.c + * @enum {string} + */ + var NaClPlugin = { + RESTART: 'r', + SAMPLE_RATE_PREFIX: 'h', + MODEL_PREFIX: 'm', + STOP: 's', + LOG: 'l', + DSP: 'd', + BEGIN_SPEAKER_MODEL: 'b', + ADAPT_SPEAKER_MODEL: 'a', + FINISH_SPEAKER_MODEL: 'f', + SPEAKER_MODEL_SAVED: 'sm_saved', + REQUEST_MODEL: 'model', + MODEL_LOADED: 'model_loaded', + READY_FOR_AUDIO: 'audio', + STOPPED: 'stopped', + HOTWORD_DETECTED: 'hotword', + MS_CONFIGURED: 'ms_configured', + TIMEOUT: 'timeout' + }; -/** - * Messages sent from the injected scripts to the Google page. - * @enum {string} - */ -var CommandToPage = { - HOTWORD_VOICE_TRIGGER: 'vt', - HOTWORD_STARTED: 'hs', - HOTWORD_ENDED: 'hd', - HOTWORD_TIMEOUT: 'ht', - HOTWORD_ERROR: 'he' -}; + /** + * Messages sent from the injected scripts to the Google page. + * @enum {string} + */ + var CommandToPage = { + HOTWORD_VOICE_TRIGGER: 'vt', + HOTWORD_STARTED: 'hs', + HOTWORD_ENDED: 'hd', + HOTWORD_TIMEOUT: 'ht', + HOTWORD_ERROR: 'he' + }; -/** - * Messages sent from the Google page to the extension or to the - * injected script and then passed to the extension. - * @enum {string} - */ -var CommandFromPage = { - SPEECH_START: 'ss', - SPEECH_END: 'se', - SPEECH_RESET: 'sr', - SHOWING_HOTWORD_START: 'shs', - SHOWING_ERROR_MESSAGE: 'sem', - SHOWING_TIMEOUT_MESSAGE: 'stm', - CLICKED_RESUME: 'hcc', - CLICKED_RESTART: 'hcr', - CLICKED_DEBUG: 'hcd', - WAKE_UP_HELPER: 'wuh', - // Command specifically for the opt-in promo below this line. - // User has explicitly clicked 'no'. - CLICKED_NO_OPTIN: 'hcno', - // User has opted in. - CLICKED_OPTIN: 'hco', - // User clicked on the microphone. - PAGE_WAKEUP: 'wu' -}; + /** + * Messages sent from the Google page to the extension or to the + * injected script and then passed to the extension. + * @enum {string} + */ + var CommandFromPage = { + SPEECH_START: 'ss', + SPEECH_END: 'se', + SPEECH_RESET: 'sr', + SHOWING_HOTWORD_START: 'shs', + SHOWING_ERROR_MESSAGE: 'sem', + SHOWING_TIMEOUT_MESSAGE: 'stm', + CLICKED_RESUME: 'hcc', + CLICKED_RESTART: 'hcr', + CLICKED_DEBUG: 'hcd', + WAKE_UP_HELPER: 'wuh', + // Command specifically for the opt-in promo below this line. + // User has explicitly clicked 'no'. + CLICKED_NO_OPTIN: 'hcno', + // User has opted in. + CLICKED_OPTIN: 'hco', + // User clicked on the microphone. + PAGE_WAKEUP: 'wu' + }; -/** - * Source of a hotwording session request. - * @enum {string} - */ -var SessionSource = { - LAUNCHER: 'launcher', - NTP: 'ntp', - ALWAYS: 'always', - TRAINING: 'training' -}; + /** + * Source of a hotwording session request. + * @enum {string} + */ + var SessionSource = { + LAUNCHER: 'launcher', + NTP: 'ntp', + ALWAYS: 'always', + TRAINING: 'training' + }; -/** - * The mode to start the hotword recognizer in. - * @enum {string} - */ -var RecognizerStartMode = { - NORMAL: 'normal', - NEW_MODEL: 'new model', - ADAPT_MODEL: 'adapt model' -}; + /** + * The mode to start the hotword recognizer in. + * @enum {string} + */ + var RecognizerStartMode = { + NORMAL: 'normal', + NEW_MODEL: 'new model', + ADAPT_MODEL: 'adapt model' + }; -/** - * MediaStream open success/errors to be reported via UMA. - * DO NOT remove or renumber values in this enum. Only add new ones. - * @enum {number} - */ -var UmaMediaStreamOpenResult = { - SUCCESS: 0, - UNKNOWN: 1, - NOT_SUPPORTED: 2, - PERMISSION_DENIED: 3, - CONSTRAINT_NOT_SATISFIED: 4, - OVERCONSTRAINED: 5, - NOT_FOUND: 6, - ABORT: 7, - SOURCE_UNAVAILABLE: 8, - PERMISSION_DISMISSED: 9, - INVALID_STATE: 10, - DEVICES_NOT_FOUND: 11, - INVALID_SECURITY_ORIGIN: 12, - MAX: 12 -}; + /** + * MediaStream open success/errors to be reported via UMA. + * DO NOT remove or renumber values in this enum. Only add new ones. + * @enum {number} + */ + var UmaMediaStreamOpenResult = { + SUCCESS: 0, + UNKNOWN: 1, + NOT_SUPPORTED: 2, + PERMISSION_DENIED: 3, + CONSTRAINT_NOT_SATISFIED: 4, + OVERCONSTRAINED: 5, + NOT_FOUND: 6, + ABORT: 7, + SOURCE_UNAVAILABLE: 8, + PERMISSION_DISMISSED: 9, + INVALID_STATE: 10, + DEVICES_NOT_FOUND: 11, + INVALID_SECURITY_ORIGIN: 12, + MAX: 12 + }; -/** - * UMA metrics. - * DO NOT change these enum values. - * @enum {string} - */ -var UmaMetrics = { - TRIGGER: 'Hotword.HotwordTrigger', - MEDIA_STREAM_RESULT: 'Hotword.HotwordMediaStreamResult', - NACL_PLUGIN_LOAD_RESULT: 'Hotword.HotwordNaClPluginLoadResult', - NACL_MESSAGE_TIMEOUT: 'Hotword.HotwordNaClMessageTimeout', - TRIGGER_SOURCE: 'Hotword.HotwordTriggerSource' -}; + /** + * UMA metrics. + * DO NOT change these enum values. + * @enum {string} + */ + var UmaMetrics = { + TRIGGER: 'Hotword.HotwordTrigger', + MEDIA_STREAM_RESULT: 'Hotword.HotwordMediaStreamResult', + NACL_PLUGIN_LOAD_RESULT: 'Hotword.HotwordNaClPluginLoadResult', + NACL_MESSAGE_TIMEOUT: 'Hotword.HotwordNaClMessageTimeout', + TRIGGER_SOURCE: 'Hotword.HotwordTriggerSource' + }; -/** - * Message waited for by NaCl plugin, to be reported via UMA. - * DO NOT remove or renumber values in this enum. Only add new ones. - * @enum {number} - */ -var UmaNaClMessageTimeout = { - REQUEST_MODEL: 0, - MODEL_LOADED: 1, - READY_FOR_AUDIO: 2, - STOPPED: 3, - HOTWORD_DETECTED: 4, - MS_CONFIGURED: 5, - MAX: 5 -}; + /** + * Message waited for by NaCl plugin, to be reported via UMA. + * DO NOT remove or renumber values in this enum. Only add new ones. + * @enum {number} + */ + var UmaNaClMessageTimeout = { + REQUEST_MODEL: 0, + MODEL_LOADED: 1, + READY_FOR_AUDIO: 2, + STOPPED: 3, + HOTWORD_DETECTED: 4, + MS_CONFIGURED: 5, + MAX: 5 + }; -/** - * NaCl plugin load success/errors to be reported via UMA. - * DO NOT remove or renumber values in this enum. Only add new ones. - * @enum {number} - */ -var UmaNaClPluginLoadResult = { - SUCCESS: 0, - UNKNOWN: 1, - CRASH: 2, - NO_MODULE_FOUND: 3, - MAX: 3 -}; + /** + * NaCl plugin load success/errors to be reported via UMA. + * DO NOT remove or renumber values in this enum. Only add new ones. + * @enum {number} + */ + var UmaNaClPluginLoadResult = + {SUCCESS: 0, UNKNOWN: 1, CRASH: 2, NO_MODULE_FOUND: 3, MAX: 3}; -/** - * Source of hotword triggering, to be reported via UMA. - * DO NOT remove or renumber values in this enum. Only add new ones. - * @enum {number} - */ -var UmaTriggerSource = { - LAUNCHER: 0, - NTP_GOOGLE_COM: 1, - ALWAYS_ON: 2, - TRAINING: 3, - MAX: 3 -}; + /** + * Source of hotword triggering, to be reported via UMA. + * DO NOT remove or renumber values in this enum. Only add new ones. + * @enum {number} + */ + var UmaTriggerSource = + {LAUNCHER: 0, NTP_GOOGLE_COM: 1, ALWAYS_ON: 2, TRAINING: 3, MAX: 3}; -/** - * The browser UI language. - * @const {string} - */ -var UI_LANGUAGE = (chrome.i18n && chrome.i18n.getUILanguage) ? - chrome.i18n.getUILanguage() : ''; + /** + * The browser UI language. + * @const {string} + */ + var UI_LANGUAGE = (chrome.i18n && chrome.i18n.getUILanguage) ? + chrome.i18n.getUILanguage() : + ''; -return { - AUDIO_LOG_SECONDS: AUDIO_LOG_SECONDS, - CLIENT_PORT_NAME: CLIENT_PORT_NAME, - COMMAND_FIELD_NAME: COMMAND_FIELD_NAME, - FILE_SYSTEM_SIZE_BYTES: FILE_SYSTEM_SIZE_BYTES, - HOTWORD_STREAM_TIMEOUT_SECONDS: HOTWORD_STREAM_TIMEOUT_SECONDS, - NUM_TRAINING_UTTERANCES: NUM_TRAINING_UTTERANCES, - SHARED_MODULE_ID: SHARED_MODULE_ID, - SHARED_MODULE_ROOT: SHARED_MODULE_ROOT, - SPEAKER_MODEL_FILE_NAME: SPEAKER_MODEL_FILE_NAME, - UI_LANGUAGE: UI_LANGUAGE, - UTTERANCE_FILE_EXTENSION: UTTERANCE_FILE_EXTENSION, - UTTERANCE_FILE_PREFIX: UTTERANCE_FILE_PREFIX, - CommandToPage: CommandToPage, - CommandFromPage: CommandFromPage, - Error: Error, - Event: Event, - File: File, - NaClPlugin: NaClPlugin, - RecognizerStartMode: RecognizerStartMode, - SessionSource: SessionSource, - TimeoutMs: TimeoutMs, - UmaMediaStreamOpenResult: UmaMediaStreamOpenResult, - UmaMetrics: UmaMetrics, - UmaNaClMessageTimeout: UmaNaClMessageTimeout, - UmaNaClPluginLoadResult: UmaNaClPluginLoadResult, - UmaTriggerSource: UmaTriggerSource -}; + return { + AUDIO_LOG_SECONDS: AUDIO_LOG_SECONDS, + CLIENT_PORT_NAME: CLIENT_PORT_NAME, + COMMAND_FIELD_NAME: COMMAND_FIELD_NAME, + FILE_SYSTEM_SIZE_BYTES: FILE_SYSTEM_SIZE_BYTES, + HOTWORD_STREAM_TIMEOUT_SECONDS: HOTWORD_STREAM_TIMEOUT_SECONDS, + NUM_TRAINING_UTTERANCES: NUM_TRAINING_UTTERANCES, + SHARED_MODULE_ID: SHARED_MODULE_ID, + SHARED_MODULE_ROOT: SHARED_MODULE_ROOT, + SPEAKER_MODEL_FILE_NAME: SPEAKER_MODEL_FILE_NAME, + UI_LANGUAGE: UI_LANGUAGE, + UTTERANCE_FILE_EXTENSION: UTTERANCE_FILE_EXTENSION, + UTTERANCE_FILE_PREFIX: UTTERANCE_FILE_PREFIX, + CommandToPage: CommandToPage, + CommandFromPage: CommandFromPage, + Error: Error, + Event: Event, + File: File, + NaClPlugin: NaClPlugin, + RecognizerStartMode: RecognizerStartMode, + SessionSource: SessionSource, + TimeoutMs: TimeoutMs, + UmaMediaStreamOpenResult: UmaMediaStreamOpenResult, + UmaMetrics: UmaMetrics, + UmaNaClMessageTimeout: UmaNaClMessageTimeout, + UmaNaClPluginLoadResult: UmaNaClPluginLoadResult, + UmaTriggerSource: UmaTriggerSource + }; });
diff --git a/chrome/browser/resources/hotword/keep_alive.js b/chrome/browser/resources/hotword/keep_alive.js index 06ddf23..20ff2ea 100644 --- a/chrome/browser/resources/hotword/keep_alive.js +++ b/chrome/browser/resources/hotword/keep_alive.js
@@ -48,7 +48,5 @@ } }; - return { - KeepAlive: KeepAlive - }; + return {KeepAlive: KeepAlive}; });
diff --git a/chrome/browser/resources/hotword/launcher_manager.js b/chrome/browser/resources/hotword/launcher_manager.js index 59646ea..144c247 100644 --- a/chrome/browser/resources/hotword/launcher_manager.js +++ b/chrome/browser/resources/hotword/launcher_manager.js
@@ -13,9 +13,8 @@ * @extends {hotword.BaseSessionManager} */ function LauncherManager(stateManager) { - hotword.BaseSessionManager.call(this, - stateManager, - hotword.constants.SessionSource.LAUNCHER); + hotword.BaseSessionManager.call( + this, stateManager, hotword.constants.SessionSource.LAUNCHER); } LauncherManager.prototype = { @@ -32,7 +31,5 @@ } }; - return { - LauncherManager: LauncherManager - }; + return {LauncherManager: LauncherManager}; });
diff --git a/chrome/browser/resources/hotword/logging.js b/chrome/browser/resources/hotword/logging.js index 307234d..e0744e0 100644 --- a/chrome/browser/resources/hotword/logging.js +++ b/chrome/browser/resources/hotword/logging.js
@@ -15,8 +15,5 @@ console.log.apply(console, arguments); } - return { - DEBUG: false, - debug: debug - }; + return {DEBUG: false, debug: debug}; });
diff --git a/chrome/browser/resources/hotword/metrics.js b/chrome/browser/resources/hotword/metrics.js index b17a5d7..7d4001bf 100644 --- a/chrome/browser/resources/hotword/metrics.js +++ b/chrome/browser/resources/hotword/metrics.js
@@ -22,7 +22,5 @@ chrome.metricsPrivate.recordValue(metricDesc, value); } - return { - recordEnum: recordEnum - }; + return {recordEnum: recordEnum}; });
diff --git a/chrome/browser/resources/hotword/nacl_manager.js b/chrome/browser/resources/hotword/nacl_manager.js index 5a1dd55..ad4a889 100644 --- a/chrome/browser/resources/hotword/nacl_manager.js +++ b/chrome/browser/resources/hotword/nacl_manager.js
@@ -3,599 +3,609 @@ // found in the LICENSE file. cr.define('hotword', function() { -'use strict'; - -/** - * Class used to manage the state of the NaCl recognizer plugin. Handles all - * control of the NaCl plugin, including creation, start, stop, trigger, and - * shutdown. - * - * @param {boolean} loggingEnabled Whether audio logging is enabled. - * @param {boolean} hotwordStream Whether the audio input stream is from a - * hotword stream. - * @constructor - * @extends {cr.EventTarget} - */ -function NaClManager(loggingEnabled, hotwordStream) { - /** - * Current state of this manager. - * @private {hotword.NaClManager.ManagerState_} - */ - this.recognizerState_ = ManagerState_.UNINITIALIZED; + 'use strict'; /** - * The window.timeout ID associated with a pending message. - * @private {?number} + * Class used to manage the state of the NaCl recognizer plugin. Handles all + * control of the NaCl plugin, including creation, start, stop, trigger, and + * shutdown. + * + * @param {boolean} loggingEnabled Whether audio logging is enabled. + * @param {boolean} hotwordStream Whether the audio input stream is from a + * hotword stream. + * @constructor + * @extends {cr.EventTarget} */ - this.naclTimeoutId_ = null; + function NaClManager(loggingEnabled, hotwordStream) { + /** + * Current state of this manager. + * @private {hotword.NaClManager.ManagerState_} + */ + this.recognizerState_ = ManagerState_.UNINITIALIZED; - /** - * The expected message that will cancel the current timeout. - * @private {?string} - */ - this.expectingMessage_ = null; + /** + * The window.timeout ID associated with a pending message. + * @private {?number} + */ + this.naclTimeoutId_ = null; - /** - * Whether the plugin will be started as soon as it stops. - * @private {boolean} - */ - this.restartOnStop_ = false; - - /** - * NaCl plugin element on extension background page. - * @private {?HTMLEmbedElement} - */ - this.plugin_ = null; - - /** - * URL containing hotword-model data file. - * @private {string} - */ - this.modelUrl_ = ''; - - /** - * Media stream containing an audio input track. - * @private {?MediaStream} - */ - this.stream_ = null; - - /** - * The mode to start the recognizer in. - * @private {?chrome.hotwordPrivate.RecognizerStartMode} - */ - this.startMode_ = hotword.constants.RecognizerStartMode.NORMAL; - - /** - * Whether audio logging is enabled. - * @private {boolean} - */ - this.loggingEnabled_ = loggingEnabled; - - /** - * Whether the audio input stream is from a hotword stream. - * @private {boolean} - */ - this.hotwordStream_ = hotwordStream; - - /** - * Audio log of X seconds before hotword triggered. - * @private {?Object} - */ - this.preambleLog_ = null; -}; - -/** - * States this manager can be in. Since messages to/from the plugin are - * asynchronous (and potentially queued), it's not possible to know what state - * the plugin is in. However, track a state machine for NaClManager based on - * what messages are sent/received. - * @enum {number} - * @private - */ -NaClManager.ManagerState_ = { - UNINITIALIZED: 0, - LOADING: 1, - STOPPING: 2, - STOPPED: 3, - STARTING: 4, - RUNNING: 5, - ERROR: 6, - SHUTDOWN: 7, -}; -var ManagerState_ = NaClManager.ManagerState_; -var Error_ = hotword.constants.Error; -var UmaNaClMessageTimeout_ = hotword.constants.UmaNaClMessageTimeout; -var UmaNaClPluginLoadResult_ = hotword.constants.UmaNaClPluginLoadResult; - -NaClManager.prototype.__proto__ = cr.EventTarget.prototype; - -/** - * Called when an error occurs. Dispatches an event. - * @param {!hotword.constants.Error} error - * @private - */ -NaClManager.prototype.handleError_ = function(error) { - var event = new Event(hotword.constants.Event.ERROR); - event.data = error; - this.dispatchEvent(event); -}; - -/** - * Record the result of loading the NaCl plugin to UMA. - * @param {!hotword.constants.UmaNaClPluginLoadResult} error - * @private - */ -NaClManager.prototype.logPluginLoadResult_ = function(error) { - hotword.metrics.recordEnum( - hotword.constants.UmaMetrics.NACL_PLUGIN_LOAD_RESULT, - error, - UmaNaClPluginLoadResult_.MAX); -}; - -/** - * Set a timeout. Only allow one timeout to exist at any given time. - * @param {!function()} func - * @param {number} timeout - * @private - */ -NaClManager.prototype.setTimeout_ = function(func, timeout) { - assert(!this.naclTimeoutId_, 'Timeout already exists'); - this.naclTimeoutId_ = window.setTimeout( - function() { - this.naclTimeoutId_ = null; - func(); - }.bind(this), timeout); -}; - -/** - * Clears the current timeout. - * @private - */ -NaClManager.prototype.clearTimeout_ = function() { - window.clearTimeout(this.naclTimeoutId_); - this.naclTimeoutId_ = null; -}; - -/** - * Starts a stopped or stopping hotword recognizer (NaCl plugin). - * @param {hotword.constants.RecognizerStartMode} mode The mode to start the - * recognizer in. - */ -NaClManager.prototype.startRecognizer = function(mode) { - this.startMode_ = mode; - if (this.recognizerState_ == ManagerState_.STOPPED) { - this.preambleLog_ = null; - this.recognizerState_ = ManagerState_.STARTING; - if (mode == hotword.constants.RecognizerStartMode.NEW_MODEL) { - hotword.debug('Starting Recognizer in START training mode'); - this.sendDataToPlugin_(hotword.constants.NaClPlugin.BEGIN_SPEAKER_MODEL); - } else if (mode == hotword.constants.RecognizerStartMode.ADAPT_MODEL) { - hotword.debug('Starting Recognizer in ADAPT training mode'); - this.sendDataToPlugin_(hotword.constants.NaClPlugin.ADAPT_SPEAKER_MODEL); - } else { - hotword.debug('Starting Recognizer in NORMAL mode'); - this.sendDataToPlugin_(hotword.constants.NaClPlugin.RESTART); - } - // Normally, there would be a waitForMessage_(READY_FOR_AUDIO) here. - // However, this message is sent the first time audio data is read and in - // some cases (ie. using the hotword stream), this won't happen until a - // potential hotword trigger is seen. Having a waitForMessage_() would time - // out in this case, so just leave it out. This ends up sacrificing a bit of - // error detection in the non-hotword-stream case, but I think we can live - // with that. - } else if (this.recognizerState_ == ManagerState_.STOPPING) { - // Wait until the plugin is stopped before trying to start it. - this.restartOnStop_ = true; - } else { - throw 'Attempting to start NaCl recogniser not in STOPPED or STOPPING ' + - 'state'; - } -}; - -/** - * Stops the hotword recognizer. - */ -NaClManager.prototype.stopRecognizer = function() { - if (this.recognizerState_ == ManagerState_.STARTING) { - // If the recognizer is stopped before it finishes starting, it causes an - // assertion to be raised in waitForMessage_() since we're waiting for the - // READY_FOR_AUDIO message. Clear the current timeout and expecting message - // since we no longer expect it and may never receive it. - this.clearTimeout_(); + /** + * The expected message that will cancel the current timeout. + * @private {?string} + */ this.expectingMessage_ = null; - } - this.sendDataToPlugin_(hotword.constants.NaClPlugin.STOP); - this.recognizerState_ = ManagerState_.STOPPING; - this.waitForMessage_(hotword.constants.TimeoutMs.NORMAL, - hotword.constants.NaClPlugin.STOPPED); -}; -/** - * Saves the speaker model. - */ -NaClManager.prototype.finalizeSpeakerModel = function() { - if (this.recognizerState_ == ManagerState_.UNINITIALIZED || - this.recognizerState_ == ManagerState_.ERROR || - this.recognizerState_ == ManagerState_.SHUTDOWN || - this.recognizerState_ == ManagerState_.LOADING) { - return; - } - this.sendDataToPlugin_(hotword.constants.NaClPlugin.FINISH_SPEAKER_MODEL); -}; + /** + * Whether the plugin will be started as soon as it stops. + * @private {boolean} + */ + this.restartOnStop_ = false; -/** + /** + * NaCl plugin element on extension background page. + * @private {?HTMLEmbedElement} + */ + this.plugin_ = null; + + /** + * URL containing hotword-model data file. + * @private {string} + */ + this.modelUrl_ = ''; + + /** + * Media stream containing an audio input track. + * @private {?MediaStream} + */ + this.stream_ = null; + + /** + * The mode to start the recognizer in. + * @private {?chrome.hotwordPrivate.RecognizerStartMode} + */ + this.startMode_ = hotword.constants.RecognizerStartMode.NORMAL; + + /** + * Whether audio logging is enabled. + * @private {boolean} + */ + this.loggingEnabled_ = loggingEnabled; + + /** + * Whether the audio input stream is from a hotword stream. + * @private {boolean} + */ + this.hotwordStream_ = hotwordStream; + + /** + * Audio log of X seconds before hotword triggered. + * @private {?Object} + */ + this.preambleLog_ = null; + }; + + /** + * States this manager can be in. Since messages to/from the plugin are + * asynchronous (and potentially queued), it's not possible to know what state + * the plugin is in. However, track a state machine for NaClManager based on + * what messages are sent/received. + * @enum {number} + * @private + */ + NaClManager.ManagerState_ = { + UNINITIALIZED: 0, + LOADING: 1, + STOPPING: 2, + STOPPED: 3, + STARTING: 4, + RUNNING: 5, + ERROR: 6, + SHUTDOWN: 7, + }; + var ManagerState_ = NaClManager.ManagerState_; + var Error_ = hotword.constants.Error; + var UmaNaClMessageTimeout_ = hotword.constants.UmaNaClMessageTimeout; + var UmaNaClPluginLoadResult_ = hotword.constants.UmaNaClPluginLoadResult; + + NaClManager.prototype.__proto__ = cr.EventTarget.prototype; + + /** + * Called when an error occurs. Dispatches an event. + * @param {!hotword.constants.Error} error + * @private + */ + NaClManager.prototype.handleError_ = function(error) { + var event = new Event(hotword.constants.Event.ERROR); + event.data = error; + this.dispatchEvent(event); + }; + + /** + * Record the result of loading the NaCl plugin to UMA. + * @param {!hotword.constants.UmaNaClPluginLoadResult} error + * @private + */ + NaClManager.prototype.logPluginLoadResult_ = function(error) { + hotword.metrics.recordEnum( + hotword.constants.UmaMetrics.NACL_PLUGIN_LOAD_RESULT, error, + UmaNaClPluginLoadResult_.MAX); + }; + + /** + * Set a timeout. Only allow one timeout to exist at any given time. + * @param {!function()} func + * @param {number} timeout + * @private + */ + NaClManager.prototype.setTimeout_ = function(func, timeout) { + assert(!this.naclTimeoutId_, 'Timeout already exists'); + this.naclTimeoutId_ = window.setTimeout(function() { + this.naclTimeoutId_ = null; + func(); + }.bind(this), timeout); + }; + + /** + * Clears the current timeout. + * @private + */ + NaClManager.prototype.clearTimeout_ = function() { + window.clearTimeout(this.naclTimeoutId_); + this.naclTimeoutId_ = null; + }; + + /** + * Starts a stopped or stopping hotword recognizer (NaCl plugin). + * @param {hotword.constants.RecognizerStartMode} mode The mode to start the + * recognizer in. + */ + NaClManager.prototype.startRecognizer = function(mode) { + this.startMode_ = mode; + if (this.recognizerState_ == ManagerState_.STOPPED) { + this.preambleLog_ = null; + this.recognizerState_ = ManagerState_.STARTING; + if (mode == hotword.constants.RecognizerStartMode.NEW_MODEL) { + hotword.debug('Starting Recognizer in START training mode'); + this.sendDataToPlugin_( + hotword.constants.NaClPlugin.BEGIN_SPEAKER_MODEL); + } else if (mode == hotword.constants.RecognizerStartMode.ADAPT_MODEL) { + hotword.debug('Starting Recognizer in ADAPT training mode'); + this.sendDataToPlugin_( + hotword.constants.NaClPlugin.ADAPT_SPEAKER_MODEL); + } else { + hotword.debug('Starting Recognizer in NORMAL mode'); + this.sendDataToPlugin_(hotword.constants.NaClPlugin.RESTART); + } + // Normally, there would be a waitForMessage_(READY_FOR_AUDIO) here. + // However, this message is sent the first time audio data is read and in + // some cases (ie. using the hotword stream), this won't happen until a + // potential hotword trigger is seen. Having a waitForMessage_() would + // time + // out in this case, so just leave it out. This ends up sacrificing a bit + // of + // error detection in the non-hotword-stream case, but I think we can live + // with that. + } else if (this.recognizerState_ == ManagerState_.STOPPING) { + // Wait until the plugin is stopped before trying to start it. + this.restartOnStop_ = true; + } else { + throw 'Attempting to start NaCl recogniser not in STOPPED or STOPPING ' + + 'state'; + } + }; + + /** + * Stops the hotword recognizer. + */ + NaClManager.prototype.stopRecognizer = function() { + if (this.recognizerState_ == ManagerState_.STARTING) { + // If the recognizer is stopped before it finishes starting, it causes an + // assertion to be raised in waitForMessage_() since we're waiting for the + // READY_FOR_AUDIO message. Clear the current timeout and expecting + // message + // since we no longer expect it and may never receive it. + this.clearTimeout_(); + this.expectingMessage_ = null; + } + this.sendDataToPlugin_(hotword.constants.NaClPlugin.STOP); + this.recognizerState_ = ManagerState_.STOPPING; + this.waitForMessage_( + hotword.constants.TimeoutMs.NORMAL, + hotword.constants.NaClPlugin.STOPPED); + }; + + /** + * Saves the speaker model. + */ + NaClManager.prototype.finalizeSpeakerModel = function() { + if (this.recognizerState_ == ManagerState_.UNINITIALIZED || + this.recognizerState_ == ManagerState_.ERROR || + this.recognizerState_ == ManagerState_.SHUTDOWN || + this.recognizerState_ == ManagerState_.LOADING) { + return; + } + this.sendDataToPlugin_(hotword.constants.NaClPlugin.FINISH_SPEAKER_MODEL); + }; + + /** * Checks whether the file at the given path exists. * @param {!string} path Path to a file. Can be any valid URL. * @return {boolean} True if the patch exists. * @private */ -NaClManager.prototype.fileExists_ = function(path) { - var xhr = new XMLHttpRequest(); - xhr.open('HEAD', path, false); - try { - xhr.send(); - } catch (err) { - return false; - } - if (xhr.readyState != xhr.DONE || xhr.status != 200) { - return false; - } - return true; -}; + NaClManager.prototype.fileExists_ = function(path) { + var xhr = new XMLHttpRequest(); + xhr.open('HEAD', path, false); + try { + xhr.send(); + } catch (err) { + return false; + } + if (xhr.readyState != xhr.DONE || xhr.status != 200) { + return false; + } + return true; + }; -/** + /** * Creates and returns a list of possible languages to check for hotword * support. * @return {!Array<string>} Array of languages. * @private */ -NaClManager.prototype.getPossibleLanguages_ = function() { - // Create array used to search first for language-country, if not found then - // search for language, if not found then no language (empty string). - // For example, search for 'en-us', then 'en', then ''. - var langs = new Array(); - if (hotword.constants.UI_LANGUAGE) { - // Chrome webstore doesn't support uppercase path: crbug.com/353407 - var language = hotword.constants.UI_LANGUAGE.toLowerCase(); - langs.push(language); // Example: 'en-us'. - // Remove country to add just the language to array. - var hyphen = language.lastIndexOf('-'); - if (hyphen >= 0) { - langs.push(language.substr(0, hyphen)); // Example: 'en'. + NaClManager.prototype.getPossibleLanguages_ = function() { + // Create array used to search first for language-country, if not found then + // search for language, if not found then no language (empty string). + // For example, search for 'en-us', then 'en', then ''. + var langs = new Array(); + if (hotword.constants.UI_LANGUAGE) { + // Chrome webstore doesn't support uppercase path: crbug.com/353407 + var language = hotword.constants.UI_LANGUAGE.toLowerCase(); + langs.push(language); // Example: 'en-us'. + // Remove country to add just the language to array. + var hyphen = language.lastIndexOf('-'); + if (hyphen >= 0) { + langs.push(language.substr(0, hyphen)); // Example: 'en'. + } } - } - langs.push(''); - return langs; -}; + langs.push(''); + return langs; + }; -/** + /** * Creates a NaCl plugin object and attaches it to the page. * @param {!string} src Location of the plugin. * @return {!HTMLEmbedElement} NaCl plugin DOM object. * @private */ -NaClManager.prototype.createPlugin_ = function(src) { - var plugin = /** @type {HTMLEmbedElement} */(document.createElement('embed')); - plugin.src = src; - plugin.type = 'application/x-nacl'; - document.body.appendChild(plugin); - return plugin; -}; + NaClManager.prototype.createPlugin_ = function(src) { + var plugin = + /** @type {HTMLEmbedElement} */ (document.createElement('embed')); + plugin.src = src; + plugin.type = 'application/x-nacl'; + document.body.appendChild(plugin); + return plugin; + }; -/** + /** * Initializes the NaCl manager. * @param {!string} naclArch Either 'arm', 'x86-32' or 'x86-64'. * @param {!MediaStream} stream A stream containing an audio source track. * @return {boolean} True if the successful. */ -NaClManager.prototype.initialize = function(naclArch, stream) { - assert(this.recognizerState_ == ManagerState_.UNINITIALIZED, - 'Recognizer not in uninitialized state. State: ' + - this.recognizerState_); - assert(this.plugin_ == null); - var langs = this.getPossibleLanguages_(); - var i, j; - // For country-lang variations. For example, when combined with path it will - // attempt to find: '/x86-32_en-gb/', else '/x86-32_en/', else '/x86-32_/'. - for (i = 0; i < langs.length; i++) { - var folder = hotword.constants.SHARED_MODULE_ROOT + '/_platform_specific/' + - naclArch + '_' + langs[i] + '/'; - var dataSrc = folder + hotword.constants.File.RECOGNIZER_CONFIG; - var pluginSrc = hotword.constants.SHARED_MODULE_ROOT + '/hotword_' + - langs[i] + '.nmf'; - var dataExists = this.fileExists_(dataSrc) && this.fileExists_(pluginSrc); - if (!dataExists) { - continue; - } + NaClManager.prototype.initialize = function(naclArch, stream) { + assert( + this.recognizerState_ == ManagerState_.UNINITIALIZED, + 'Recognizer not in uninitialized state. State: ' + + this.recognizerState_); + assert(this.plugin_ == null); + var langs = this.getPossibleLanguages_(); + var i, j; + // For country-lang variations. For example, when combined with path it will + // attempt to find: '/x86-32_en-gb/', else '/x86-32_en/', else '/x86-32_/'. + for (i = 0; i < langs.length; i++) { + var folder = hotword.constants.SHARED_MODULE_ROOT + + '/_platform_specific/' + naclArch + '_' + langs[i] + '/'; + var dataSrc = folder + hotword.constants.File.RECOGNIZER_CONFIG; + var pluginSrc = hotword.constants.SHARED_MODULE_ROOT + '/hotword_' + + langs[i] + '.nmf'; + var dataExists = this.fileExists_(dataSrc) && this.fileExists_(pluginSrc); + if (!dataExists) { + continue; + } - var plugin = this.createPlugin_(pluginSrc); - if (!plugin || !plugin.postMessage) { - document.body.removeChild(plugin); - this.recognizerState_ = ManagerState_.ERROR; - return false; - } - this.plugin_ = plugin; - this.modelUrl_ = chrome.extension.getURL(dataSrc); - this.stream_ = stream; - this.recognizerState_ = ManagerState_.LOADING; - - plugin.addEventListener('message', - this.handlePluginMessage_.bind(this), - false); - - plugin.addEventListener('crash', - function() { - this.handleError_(Error_.NACL_CRASH); - this.logPluginLoadResult_( - UmaNaClPluginLoadResult_.CRASH); - }.bind(this), - false); - return true; - } - this.recognizerState_ = ManagerState_.ERROR; - this.logPluginLoadResult_(UmaNaClPluginLoadResult_.NO_MODULE_FOUND); - return false; -}; - -/** - * Shuts down the NaCl plugin and frees all resources. - */ -NaClManager.prototype.shutdown = function() { - if (this.plugin_ != null) { - document.body.removeChild(this.plugin_); - this.plugin_ = null; - } - this.clearTimeout_(); - this.recognizerState_ = ManagerState_.SHUTDOWN; - if (this.stream_) - this.stream_.getAudioTracks()[0].stop(); - this.stream_ = null; -}; - -/** - * Sends data to the NaCl plugin. - * @param {!string|!MediaStreamTrack} data Command to be sent to NaCl plugin. - * @private - */ -NaClManager.prototype.sendDataToPlugin_ = function(data) { - assert(this.recognizerState_ != ManagerState_.UNINITIALIZED, - 'Recognizer in uninitialized state'); - this.plugin_.postMessage(data); -}; - -/** - * Waits, with a timeout, for a message to be received from the plugin. If the - * message is not seen within the timeout, dispatch an 'error' event and go into - * the ERROR state. - * @param {number} timeout Timeout, in milliseconds, to wait for the message. - * @param {!string} message Message to wait for. - * @private - */ -NaClManager.prototype.waitForMessage_ = function(timeout, message) { - assert(this.expectingMessage_ == null, 'Cannot wait for message: ' + - message + ', already waiting for message ' + this.expectingMessage_); - this.setTimeout_( - function() { + var plugin = this.createPlugin_(pluginSrc); + if (!plugin || !plugin.postMessage) { + document.body.removeChild(plugin); this.recognizerState_ = ManagerState_.ERROR; - this.handleError_(Error_.TIMEOUT); - switch (this.expectingMessage_) { - case hotword.constants.NaClPlugin.REQUEST_MODEL: - var metricValue = UmaNaClMessageTimeout_.REQUEST_MODEL; - break; - case hotword.constants.NaClPlugin.MODEL_LOADED: - var metricValue = UmaNaClMessageTimeout_.MODEL_LOADED; - break; - case hotword.constants.NaClPlugin.READY_FOR_AUDIO: - var metricValue = UmaNaClMessageTimeout_.READY_FOR_AUDIO; - break; - case hotword.constants.NaClPlugin.STOPPED: - var metricValue = UmaNaClMessageTimeout_.STOPPED; - break; - case hotword.constants.NaClPlugin.HOTWORD_DETECTED: - var metricValue = UmaNaClMessageTimeout_.HOTWORD_DETECTED; - break; - case hotword.constants.NaClPlugin.MS_CONFIGURED: - var metricValue = UmaNaClMessageTimeout_.MS_CONFIGURED; - break; - } - hotword.metrics.recordEnum( - hotword.constants.UmaMetrics.NACL_MESSAGE_TIMEOUT, - metricValue, - UmaNaClMessageTimeout_.MAX); - }.bind(this), timeout); - this.expectingMessage_ = message; -}; + return false; + } + this.plugin_ = plugin; + this.modelUrl_ = chrome.extension.getURL(dataSrc); + this.stream_ = stream; + this.recognizerState_ = ManagerState_.LOADING; -/** - * Called when a message is received from the plugin. If we're waiting for that - * message, cancel the pending timeout. - * @param {string} message Message received. - * @private - */ -NaClManager.prototype.receivedMessage_ = function(message) { - if (message == this.expectingMessage_) { + plugin.addEventListener( + 'message', this.handlePluginMessage_.bind(this), false); + + plugin.addEventListener('crash', function() { + this.handleError_(Error_.NACL_CRASH); + this.logPluginLoadResult_(UmaNaClPluginLoadResult_.CRASH); + }.bind(this), false); + return true; + } + this.recognizerState_ = ManagerState_.ERROR; + this.logPluginLoadResult_(UmaNaClPluginLoadResult_.NO_MODULE_FOUND); + return false; + }; + + /** + * Shuts down the NaCl plugin and frees all resources. + */ + NaClManager.prototype.shutdown = function() { + if (this.plugin_ != null) { + document.body.removeChild(this.plugin_); + this.plugin_ = null; + } this.clearTimeout_(); - this.expectingMessage_ = null; - } -}; + this.recognizerState_ = ManagerState_.SHUTDOWN; + if (this.stream_) + this.stream_.getAudioTracks()[0].stop(); + this.stream_ = null; + }; -/** - * Handle a REQUEST_MODEL message from the plugin. - * The plugin sends this message immediately after starting. - * @private - */ -NaClManager.prototype.handleRequestModel_ = function() { - if (this.recognizerState_ != ManagerState_.LOADING) { - return; - } - this.logPluginLoadResult_(UmaNaClPluginLoadResult_.SUCCESS); - this.sendDataToPlugin_( - hotword.constants.NaClPlugin.MODEL_PREFIX + this.modelUrl_); - this.waitForMessage_(hotword.constants.TimeoutMs.LONG, - hotword.constants.NaClPlugin.MODEL_LOADED); + /** + * Sends data to the NaCl plugin. + * @param {!string|!MediaStreamTrack} data Command to be sent to NaCl plugin. + * @private + */ + NaClManager.prototype.sendDataToPlugin_ = function(data) { + assert( + this.recognizerState_ != ManagerState_.UNINITIALIZED, + 'Recognizer in uninitialized state'); + this.plugin_.postMessage(data); + }; - // Configure logging in the plugin. This can be configured any time before - // starting the recognizer, and now is as good a time as any. - if (this.loggingEnabled_) { - this.sendDataToPlugin_( - hotword.constants.NaClPlugin.LOG + ':' + - hotword.constants.AUDIO_LOG_SECONDS); - } + /** + * Waits, with a timeout, for a message to be received from the plugin. If the + * message is not seen within the timeout, dispatch an 'error' event and go + * into + * the ERROR state. + * @param {number} timeout Timeout, in milliseconds, to wait for the message. + * @param {!string} message Message to wait for. + * @private + */ + NaClManager.prototype.waitForMessage_ = function(timeout, message) { + assert( + this.expectingMessage_ == null, 'Cannot wait for message: ' + message + + ', already waiting for message ' + this.expectingMessage_); + this.setTimeout_(function() { + this.recognizerState_ = ManagerState_.ERROR; + this.handleError_(Error_.TIMEOUT); + switch (this.expectingMessage_) { + case hotword.constants.NaClPlugin.REQUEST_MODEL: + var metricValue = UmaNaClMessageTimeout_.REQUEST_MODEL; + break; + case hotword.constants.NaClPlugin.MODEL_LOADED: + var metricValue = UmaNaClMessageTimeout_.MODEL_LOADED; + break; + case hotword.constants.NaClPlugin.READY_FOR_AUDIO: + var metricValue = UmaNaClMessageTimeout_.READY_FOR_AUDIO; + break; + case hotword.constants.NaClPlugin.STOPPED: + var metricValue = UmaNaClMessageTimeout_.STOPPED; + break; + case hotword.constants.NaClPlugin.HOTWORD_DETECTED: + var metricValue = UmaNaClMessageTimeout_.HOTWORD_DETECTED; + break; + case hotword.constants.NaClPlugin.MS_CONFIGURED: + var metricValue = UmaNaClMessageTimeout_.MS_CONFIGURED; + break; + } + hotword.metrics.recordEnum( + hotword.constants.UmaMetrics.NACL_MESSAGE_TIMEOUT, metricValue, + UmaNaClMessageTimeout_.MAX); + }.bind(this), timeout); + this.expectingMessage_ = message; + }; - // If the audio stream is from a hotword stream, tell the plugin. - if (this.hotwordStream_) { - this.sendDataToPlugin_( - hotword.constants.NaClPlugin.DSP + ':' + - hotword.constants.HOTWORD_STREAM_TIMEOUT_SECONDS); - } -}; + /** + * Called when a message is received from the plugin. If we're waiting for + * that + * message, cancel the pending timeout. + * @param {string} message Message received. + * @private + */ + NaClManager.prototype.receivedMessage_ = function(message) { + if (message == this.expectingMessage_) { + this.clearTimeout_(); + this.expectingMessage_ = null; + } + }; -/** - * Handle a MODEL_LOADED message from the plugin. - * The plugin sends this message after successfully loading the language model. - * @private - */ -NaClManager.prototype.handleModelLoaded_ = function() { - if (this.recognizerState_ != ManagerState_.LOADING) { - return; - } - this.sendDataToPlugin_(this.stream_.getAudioTracks()[0]); - // The plugin will send a MS_CONFIGURED, but don't set a timeout waiting for - // it. MediaStreamAudioTrack::Configure() will remain pending until the first - // audio buffer is received. When the audio source is a DSP for always-on - // detection, no audio sample is sent until the DSP detects a potential - // hotword trigger. Thus, Configure would remain pending indefinitely if we - // were to wait here. See https://crbug.com/616203 -}; - -/** - * Handle a MS_CONFIGURED message from the plugin. - * The plugin sends this message after successfully configuring the audio input - * stream. - * @private - */ -NaClManager.prototype.handleMsConfigured_ = function() { - if (this.recognizerState_ != ManagerState_.LOADING) { - return; - } - this.recognizerState_ = ManagerState_.STOPPED; - this.dispatchEvent(new Event(hotword.constants.Event.READY)); -}; - -/** - * Handle a READY_FOR_AUDIO message from the plugin. - * The plugin sends this message after the recognizer is started and - * successfully receives and processes audio data. - * @private - */ -NaClManager.prototype.handleReadyForAudio_ = function() { - if (this.recognizerState_ != ManagerState_.STARTING) { - return; - } - this.recognizerState_ = ManagerState_.RUNNING; -}; - -/** - * Handle a HOTWORD_DETECTED message from the plugin. - * The plugin sends this message after detecting the hotword. - * @private - */ -NaClManager.prototype.handleHotwordDetected_ = function() { - if (this.recognizerState_ != ManagerState_.RUNNING) { - return; - } - // We'll receive a STOPPED message very soon. - this.recognizerState_ = ManagerState_.STOPPING; - this.waitForMessage_(hotword.constants.TimeoutMs.NORMAL, - hotword.constants.NaClPlugin.STOPPED); - var event = new Event(hotword.constants.Event.TRIGGER); - event.log = this.preambleLog_; - this.dispatchEvent(event); -}; - -/** - * Handle a STOPPED message from the plugin. - * This plugin sends this message after stopping the recognizer. This can happen - * either in response to a stop request, or after the hotword is detected. - * @private - */ -NaClManager.prototype.handleStopped_ = function() { - this.recognizerState_ = ManagerState_.STOPPED; - if (this.restartOnStop_) { - this.restartOnStop_ = false; - this.startRecognizer(this.startMode_); - } -}; - -/** - * Handle a TIMEOUT message from the plugin. - * The plugin sends this message when it thinks the stream is from a DSP and - * a hotword wasn't detected within a timeout period after arrival of the first - * audio samples. - * @private - */ -NaClManager.prototype.handleTimeout_ = function() { - if (this.recognizerState_ != ManagerState_.RUNNING) { - return; - } - this.recognizerState_ = ManagerState_.STOPPED; - this.dispatchEvent(new Event(hotword.constants.Event.TIMEOUT)); -}; - -/** - * Handle a SPEAKER_MODEL_SAVED message from the plugin. - * The plugin sends this message after writing the model to a file. - * @private - */ -NaClManager.prototype.handleSpeakerModelSaved_ = function() { - this.dispatchEvent(new Event(hotword.constants.Event.SPEAKER_MODEL_SAVED)); -}; - -/** - * Handles a message from the NaCl plugin. - * @param {!Event} msg Message from NaCl plugin. - * @private - */ -NaClManager.prototype.handlePluginMessage_ = function(msg) { - if (msg['data']) { - if (typeof(msg['data']) == 'object') { - // Save the preamble for delivery to the trigger handler when the trigger - // message arrives. - this.preambleLog_ = msg['data']; + /** + * Handle a REQUEST_MODEL message from the plugin. + * The plugin sends this message immediately after starting. + * @private + */ + NaClManager.prototype.handleRequestModel_ = function() { + if (this.recognizerState_ != ManagerState_.LOADING) { return; } - this.receivedMessage_(msg['data']); - switch (msg['data']) { - case hotword.constants.NaClPlugin.REQUEST_MODEL: - this.handleRequestModel_(); - break; - case hotword.constants.NaClPlugin.MODEL_LOADED: - this.handleModelLoaded_(); - break; - case hotword.constants.NaClPlugin.MS_CONFIGURED: - this.handleMsConfigured_(); - break; - case hotword.constants.NaClPlugin.READY_FOR_AUDIO: - this.handleReadyForAudio_(); - break; - case hotword.constants.NaClPlugin.HOTWORD_DETECTED: - this.handleHotwordDetected_(); - break; - case hotword.constants.NaClPlugin.STOPPED: - this.handleStopped_(); - break; - case hotword.constants.NaClPlugin.TIMEOUT: - this.handleTimeout_(); - break; - case hotword.constants.NaClPlugin.SPEAKER_MODEL_SAVED: - this.handleSpeakerModelSaved_(); - break; - } - } -}; + this.logPluginLoadResult_(UmaNaClPluginLoadResult_.SUCCESS); + this.sendDataToPlugin_( + hotword.constants.NaClPlugin.MODEL_PREFIX + this.modelUrl_); + this.waitForMessage_( + hotword.constants.TimeoutMs.LONG, + hotword.constants.NaClPlugin.MODEL_LOADED); -return { - NaClManager: NaClManager -}; + // Configure logging in the plugin. This can be configured any time before + // starting the recognizer, and now is as good a time as any. + if (this.loggingEnabled_) { + this.sendDataToPlugin_( + hotword.constants.NaClPlugin.LOG + ':' + + hotword.constants.AUDIO_LOG_SECONDS); + } + + // If the audio stream is from a hotword stream, tell the plugin. + if (this.hotwordStream_) { + this.sendDataToPlugin_( + hotword.constants.NaClPlugin.DSP + ':' + + hotword.constants.HOTWORD_STREAM_TIMEOUT_SECONDS); + } + }; + + /** + * Handle a MODEL_LOADED message from the plugin. + * The plugin sends this message after successfully loading the language + * model. + * @private + */ + NaClManager.prototype.handleModelLoaded_ = function() { + if (this.recognizerState_ != ManagerState_.LOADING) { + return; + } + this.sendDataToPlugin_(this.stream_.getAudioTracks()[0]); + // The plugin will send a MS_CONFIGURED, but don't set a timeout waiting for + // it. MediaStreamAudioTrack::Configure() will remain pending until the + // first + // audio buffer is received. When the audio source is a DSP for always-on + // detection, no audio sample is sent until the DSP detects a potential + // hotword trigger. Thus, Configure would remain pending indefinitely if we + // were to wait here. See https://crbug.com/616203 + }; + + /** + * Handle a MS_CONFIGURED message from the plugin. + * The plugin sends this message after successfully configuring the audio + * input + * stream. + * @private + */ + NaClManager.prototype.handleMsConfigured_ = function() { + if (this.recognizerState_ != ManagerState_.LOADING) { + return; + } + this.recognizerState_ = ManagerState_.STOPPED; + this.dispatchEvent(new Event(hotword.constants.Event.READY)); + }; + + /** + * Handle a READY_FOR_AUDIO message from the plugin. + * The plugin sends this message after the recognizer is started and + * successfully receives and processes audio data. + * @private + */ + NaClManager.prototype.handleReadyForAudio_ = function() { + if (this.recognizerState_ != ManagerState_.STARTING) { + return; + } + this.recognizerState_ = ManagerState_.RUNNING; + }; + + /** + * Handle a HOTWORD_DETECTED message from the plugin. + * The plugin sends this message after detecting the hotword. + * @private + */ + NaClManager.prototype.handleHotwordDetected_ = function() { + if (this.recognizerState_ != ManagerState_.RUNNING) { + return; + } + // We'll receive a STOPPED message very soon. + this.recognizerState_ = ManagerState_.STOPPING; + this.waitForMessage_( + hotword.constants.TimeoutMs.NORMAL, + hotword.constants.NaClPlugin.STOPPED); + var event = new Event(hotword.constants.Event.TRIGGER); + event.log = this.preambleLog_; + this.dispatchEvent(event); + }; + + /** + * Handle a STOPPED message from the plugin. + * This plugin sends this message after stopping the recognizer. This can + * happen + * either in response to a stop request, or after the hotword is detected. + * @private + */ + NaClManager.prototype.handleStopped_ = function() { + this.recognizerState_ = ManagerState_.STOPPED; + if (this.restartOnStop_) { + this.restartOnStop_ = false; + this.startRecognizer(this.startMode_); + } + }; + + /** + * Handle a TIMEOUT message from the plugin. + * The plugin sends this message when it thinks the stream is from a DSP and + * a hotword wasn't detected within a timeout period after arrival of the + * first + * audio samples. + * @private + */ + NaClManager.prototype.handleTimeout_ = function() { + if (this.recognizerState_ != ManagerState_.RUNNING) { + return; + } + this.recognizerState_ = ManagerState_.STOPPED; + this.dispatchEvent(new Event(hotword.constants.Event.TIMEOUT)); + }; + + /** + * Handle a SPEAKER_MODEL_SAVED message from the plugin. + * The plugin sends this message after writing the model to a file. + * @private + */ + NaClManager.prototype.handleSpeakerModelSaved_ = function() { + this.dispatchEvent(new Event(hotword.constants.Event.SPEAKER_MODEL_SAVED)); + }; + + /** + * Handles a message from the NaCl plugin. + * @param {!Event} msg Message from NaCl plugin. + * @private + */ + NaClManager.prototype.handlePluginMessage_ = function(msg) { + if (msg['data']) { + if (typeof(msg['data']) == 'object') { + // Save the preamble for delivery to the trigger handler when the + // trigger + // message arrives. + this.preambleLog_ = msg['data']; + return; + } + this.receivedMessage_(msg['data']); + switch (msg['data']) { + case hotword.constants.NaClPlugin.REQUEST_MODEL: + this.handleRequestModel_(); + break; + case hotword.constants.NaClPlugin.MODEL_LOADED: + this.handleModelLoaded_(); + break; + case hotword.constants.NaClPlugin.MS_CONFIGURED: + this.handleMsConfigured_(); + break; + case hotword.constants.NaClPlugin.READY_FOR_AUDIO: + this.handleReadyForAudio_(); + break; + case hotword.constants.NaClPlugin.HOTWORD_DETECTED: + this.handleHotwordDetected_(); + break; + case hotword.constants.NaClPlugin.STOPPED: + this.handleStopped_(); + break; + case hotword.constants.NaClPlugin.TIMEOUT: + this.handleTimeout_(); + break; + case hotword.constants.NaClPlugin.SPEAKER_MODEL_SAVED: + this.handleSpeakerModelSaved_(); + break; + } + } + }; + + return {NaClManager: NaClManager}; });
diff --git a/chrome/browser/resources/hotword/page_audio_manager.js b/chrome/browser/resources/hotword/page_audio_manager.js index d5cdc86..5d45d00 100644 --- a/chrome/browser/resources/hotword/page_audio_manager.js +++ b/chrome/browser/resources/hotword/page_audio_manager.js
@@ -62,13 +62,10 @@ * @private */ checkUrlPathIsEligible_: function(url, base) { - if (url == base || - url == base + '/' || + if (url == base || url == base + '/' || url.startsWith(base + '/_/chrome/newtab?') || // Appcache NTP. - url.startsWith(base + '/?') || - url.startsWith(base + '/#') || - url.startsWith(base + '/webhp') || - url.startsWith(base + '/search') || + url.startsWith(base + '/?') || url.startsWith(base + '/#') || + url.startsWith(base + '/webhp') || url.startsWith(base + '/search') || url.startsWith(base + '/imghp')) { return true; } @@ -87,28 +84,13 @@ return false; var baseGoogleUrls = [ - 'https://encrypted.google.', - 'https://images.google.', + 'https://encrypted.google.', 'https://images.google.', 'https://www.google.' ]; // TODO(amistry): Get this list from a file in the shared module instead. var tlds = [ - 'at', - 'ca', - 'com', - 'com.au', - 'com.mx', - 'com.br', - 'co.jp', - 'co.kr', - 'co.nz', - 'co.uk', - 'co.za', - 'de', - 'es', - 'fr', - 'it', - 'ru' + 'at', 'ca', 'com', 'com.au', 'com.mx', 'com.br', 'co.jp', 'co.kr', + 'co.nz', 'co.uk', 'co.za', 'de', 'es', 'fr', 'it', 'ru' ]; // Check for the new tab page first. @@ -135,23 +117,21 @@ * @private */ findCurrentTab_: function(callback) { - chrome.windows.getAll( - {'populate': true}, - function(windows) { - for (var i = 0; i < windows.length; ++i) { - if (!windows[i].focused) - continue; + chrome.windows.getAll({'populate': true}, function(windows) { + for (var i = 0; i < windows.length; ++i) { + if (!windows[i].focused) + continue; - for (var j = 0; j < windows[i].tabs.length; ++j) { - var tab = windows[i].tabs[j]; - if (tab.active) { - callback.call(this, tab); - return; - } - } + for (var j = 0; j < windows[i].tabs.length; ++j) { + var tab = windows[i].tabs[j]; + if (tab.active) { + callback.call(this, tab); + return; } - callback.call(this, null); - }.bind(this)); + } + } + callback.call(this, null); + }.bind(this)); }, /** @@ -182,9 +162,7 @@ return; chrome.tabs.executeScript( - tab.id, - {'file': 'audio_client.js'}, - function(results) { + tab.id, {'file': 'audio_client.js'}, function(results) { if (chrome.runtime.lastError) { // Ignore this error. For new tab pages, even though the URL is // reported to be chrome://newtab/, the actual URL is a @@ -274,7 +252,7 @@ if (port.name != hotword.constants.CLIENT_PORT_NAME) return; - var tab = /** @type {!Tab} */(port.sender.tab); + var tab = /** @type {!Tab} */ (port.sender.tab); // An existing port from the same tab might already exist. But that port // may be from the previous page, so just overwrite the port. this.portMap_[tab.id] = port; @@ -358,11 +336,9 @@ */ startHotwording_: function() { this.stateManager_.startSession( - hotword.constants.SessionSource.NTP, - function() { + hotword.constants.SessionSource.NTP, function() { this.sendAllClients_(CommandToPage.HOTWORD_STARTED); - }.bind(this), - this.hotwordTriggered_.bind(this)); + }.bind(this), this.hotwordTriggered_.bind(this)); }, /** @@ -444,8 +420,7 @@ chrome.hotwordPrivate.getStatus( true /* getOptionalFields */, this.statusDone_.bind( - this, - request.tab || sender.tab || {incognito: true}, + this, request.tab || sender.tab || {incognito: true}, sendResponse)); return true; } @@ -527,8 +502,7 @@ this.microphoneStateChangedListener_); if (chrome.runtime.onMessage.hasListener(this.messageListener_)) return; - chrome.runtime.onMessageExternal.addListener( - this.messageListener_); + chrome.runtime.onMessageExternal.addListener(this.messageListener_); }, /** @@ -563,7 +537,5 @@ } }; - return { - PageAudioManager: PageAudioManager - }; + return {PageAudioManager: PageAudioManager}; });
diff --git a/chrome/browser/resources/hotword/state_manager.js b/chrome/browser/resources/hotword/state_manager.js index a7939b1..98e0a5c 100644 --- a/chrome/browser/resources/hotword/state_manager.js +++ b/chrome/browser/resources/hotword/state_manager.js
@@ -26,10 +26,10 @@ */ this.source_ = source; - /** - * Callback invoked when the hotword has triggered. - * @private {!function()} - */ + /** + * Callback invoked when the hotword has triggered. + * @private {!function()} + */ this.triggerCb_ = triggerCb; /** @@ -93,7 +93,7 @@ * @private {!HTMLAudioElement} */ this.chime_ = - /** @type {!HTMLAudioElement} */(document.createElement('audio')); + /** @type {!HTMLAudioElement} */ (document.createElement('audio')); /** * Chrome event listeners. Saved so that they can be de-registered when @@ -216,8 +216,8 @@ * @return {boolean} True if google.com/NTP/launcher hotwording is enabled. */ isSometimesOnEnabled: function() { - assert(this.hotwordStatus_, - 'No hotwording status (isSometimesOnEnabled)'); + assert( + this.hotwordStatus_, 'No hotwording status (isSometimesOnEnabled)'); // Although the two settings are supposed to be mutually exclusive, it's // possible for both to be set. In that case, always-on takes precedence. return this.hotwordStatus_.enabled && @@ -263,8 +263,7 @@ if (!this.hotwordStatus_) return; - if (this.hotwordStatus_.enabled || - this.hotwordStatus_.alwaysOnEnabled || + if (this.hotwordStatus_.enabled || this.hotwordStatus_.alwaysOnEnabled || this.hotwordStatus_.trainingEnabled) { // Detect changes to audio logging and kill the detector if that setting // has changed. @@ -322,16 +321,16 @@ this.state_ = State_.STARTING; var isHotwordStream = this.isAlwaysOnEnabled() && this.hotwordStatus_.hotwordHardwareAvailable; - this.pluginManager_ = new hotword.NaClManager(this.loggingEnabled_, - isHotwordStream); - this.pluginManager_.addEventListener(hotword.constants.Event.READY, - this.onReady_.bind(this)); - this.pluginManager_.addEventListener(hotword.constants.Event.ERROR, - this.onError_.bind(this)); - this.pluginManager_.addEventListener(hotword.constants.Event.TRIGGER, - this.onTrigger_.bind(this)); - this.pluginManager_.addEventListener(hotword.constants.Event.TIMEOUT, - this.onTimeout_.bind(this)); + this.pluginManager_ = + new hotword.NaClManager(this.loggingEnabled_, isHotwordStream); + this.pluginManager_.addEventListener( + hotword.constants.Event.READY, this.onReady_.bind(this)); + this.pluginManager_.addEventListener( + hotword.constants.Event.ERROR, this.onError_.bind(this)); + this.pluginManager_.addEventListener( + hotword.constants.Event.TRIGGER, this.onTrigger_.bind(this)); + this.pluginManager_.addEventListener( + hotword.constants.Event.TIMEOUT, this.onTimeout_.bind(this)); this.pluginManager_.addEventListener( hotword.constants.Event.SPEAKER_MODEL_SAVED, this.onSpeakerModelSaved_.bind(this)); @@ -346,10 +345,14 @@ // detection via a flag, and hence the hotword stream may not be // available. var constraints = /** @type {googMediaStreamConstraints} */ - ({audio: {optional: [ - { googDucking: false }, - { googHotword: this.isAlwaysOnEnabled() } - ]}}); + ({ + audio: { + optional: [ + {googDucking: false}, + {googHotword: this.isAlwaysOnEnabled()} + ] + } + }); navigator.webkitGetUserMedia( /** @type {MediaStreamConstraints} */ (constraints), function(stream) { @@ -452,8 +455,9 @@ * started. */ finalizeSpeakerModel: function() { - assert(this.pluginManager_, - 'Cannot finalize speaker model: No NaCl plugin loaded'); + assert( + this.pluginManager_, + 'Cannot finalize speaker model: No NaCl plugin loaded'); if (this.state_ != State_.RUNNING) { hotword.debug('Cannot finalize speaker model: NaCl plugin not started'); return; @@ -577,8 +581,8 @@ * @param {hotword.constants.RecognizerStartMode=} opt_mode The mode to * start the recognizer in. */ - startSession: function(source, startedCb, triggerCb, - opt_modelSavedCb, opt_mode) { + startSession: function( + source, startedCb, triggerCb, opt_modelSavedCb, opt_mode) { if (this.isTrainingEnabled() && opt_mode) { this.startMode_ = opt_mode; } else { @@ -586,8 +590,8 @@ } hotword.debug('Starting session for source: ' + source); this.removeSession_(source); - this.sessions_.push(new Session_(source, triggerCb, startedCb, - opt_modelSavedCb)); + this.sessions_.push( + new Session_(source, triggerCb, startedCb, opt_modelSavedCb)); this.updateStateFromStatus_(); }, @@ -633,7 +637,5 @@ } }; - return { - StateManager: StateManager - }; + return {StateManager: StateManager}; });
diff --git a/chrome/browser/resources/hotword/training_manager.js b/chrome/browser/resources/hotword/training_manager.js index 15752eb1..f5b68d4 100644 --- a/chrome/browser/resources/hotword/training_manager.js +++ b/chrome/browser/resources/hotword/training_manager.js
@@ -22,9 +22,8 @@ this.finalizedSpeakerModelListener_ = this.handleFinalizeSpeakerModel_.bind(this); - hotword.BaseSessionManager.call(this, - stateManager, - hotword.constants.SessionSource.TRAINING); + hotword.BaseSessionManager.call( + this, stateManager, hotword.constants.SessionSource.TRAINING); } /** @@ -34,14 +33,16 @@ * @private */ TrainingManager.deleteFiles_ = function(fs) { - fs.root.getFile(hotword.constants.SPEAKER_MODEL_FILE_NAME, {create: false}, + fs.root.getFile( + hotword.constants.SPEAKER_MODEL_FILE_NAME, {create: false}, TrainingManager.deleteFile_, TrainingManager.fileErrorHandler_); for (var i = 0; i < hotword.constants.NUM_TRAINING_UTTERANCES; ++i) { - fs.root.getFile(hotword.constants.UTTERANCE_FILE_PREFIX + i + - hotword.constants.UTTERANCE_FILE_EXTENSION, - {create: false}, - TrainingManager.deleteFile_, TrainingManager.fileErrorHandler_); + fs.root.getFile( + hotword.constants.UTTERANCE_FILE_PREFIX + i + + hotword.constants.UTTERANCE_FILE_EXTENSION, + {create: false}, TrainingManager.deleteFile_, + TrainingManager.fileErrorHandler_); } }; @@ -59,7 +60,7 @@ }); } fileEntry.remove(function() { - hotword.debug('File removed: ' + fileEntry.fullPath); + hotword.debug('File removed: ' + fileEntry.fullPath); }, TrainingManager.fileErrorHandler_); } }; @@ -70,7 +71,7 @@ * @private */ TrainingManager.fileErrorHandler_ = function(e) { - hotword.debug('File error: ' + e.code); + hotword.debug('File error: ' + e.code); }; /** @@ -89,7 +90,8 @@ * @private */ TrainingManager.speakerModelExists_ = function(fs) { - fs.root.getFile(hotword.constants.SPEAKER_MODEL_FILE_NAME, {create: false}, + fs.root.getFile( + hotword.constants.SPEAKER_MODEL_FILE_NAME, {create: false}, TrainingManager.sendSpeakerModelExistsResponse_, TrainingManager.sendNoSpeakerModelResponse_); }; @@ -116,29 +118,27 @@ * Handles a request to delete the speaker model. */ TrainingManager.handleDeleteSpeakerModel = function() { - window.webkitRequestFileSystem(PERSISTENT, - hotword.constants.FILE_SYSTEM_SIZE_BYTES, - TrainingManager.deleteFiles_, - TrainingManager.fileErrorHandler_); + window.webkitRequestFileSystem( + PERSISTENT, hotword.constants.FILE_SYSTEM_SIZE_BYTES, + TrainingManager.deleteFiles_, TrainingManager.fileErrorHandler_); }; /** * Handles a request for the speaker model existence. */ TrainingManager.handleSpeakerModelExists = function() { - window.webkitRequestFileSystem(PERSISTENT, - hotword.constants.FILE_SYSTEM_SIZE_BYTES, - TrainingManager.speakerModelExists_, - TrainingManager.fileErrorHandler_); + window.webkitRequestFileSystem( + PERSISTENT, hotword.constants.FILE_SYSTEM_SIZE_BYTES, + TrainingManager.speakerModelExists_, TrainingManager.fileErrorHandler_); }; TrainingManager.prototype = { __proto__: hotword.BaseSessionManager.prototype, /** @override */ - enabled: function() { - return this.stateManager.isTrainingEnabled(); - }, + enabled: function() { + return this.stateManager.isTrainingEnabled(); + }, /** @override */ updateListeners: function() { @@ -175,8 +175,7 @@ chrome.hotwordPrivate.setHotwordSessionState(true, function() {}); }, this.handleHotwordTrigger.bind(this), - this.handleSpeakerModelSaved_.bind(this), - opt_mode); + this.handleSpeakerModelSaved_.bind(this), opt_mode); }, /** @@ -198,7 +197,5 @@ }, }; - return { - TrainingManager: TrainingManager - }; + return {TrainingManager: TrainingManager}; });
diff --git a/chrome/browser/resources/net_internals/source_entry.js b/chrome/browser/resources/net_internals/source_entry.js index bca0e04b..14e98a4 100644 --- a/chrome/browser/resources/net_internals/source_entry.js +++ b/chrome/browser/resources/net_internals/source_entry.js
@@ -186,8 +186,10 @@ /** * Returns the starting entry for this source. Conceptually this is the * first entry that was logged to this source. However, we skip over the - * TYPE_REQUEST_ALIVE entries which wrap TYPE_URL_REQUEST_START_JOB - * entries. + * TYPE_REQUEST_ALIVE entries without parameters which wrap + * TYPE_URL_REQUEST_START_JOB entries. (TYPE_REQUEST_ALIVE may or may not + * have parameters depending on what version of Chromium they were + * generated from.) */ getStartEntry_: function() { if (this.entries_.length < 1)
diff --git a/chrome/browser/resources/settings/internet_page/internet_detail_page.js b/chrome/browser/resources/settings/internet_page/internet_detail_page.js index 246ea761..0c92ba54 100644 --- a/chrome/browser/resources/settings/internet_page/internet_detail_page.js +++ b/chrome/browser/resources/settings/internet_page/internet_detail_page.js
@@ -459,9 +459,8 @@ /** @private */ onForgetTap_: function() { this.networkingPrivate.forgetNetwork(this.guid); - // A forgotten WiFi network can still be configured, but not other types. - if (this.networkProperties.Type != CrOnc.Type.WI_FI) - this.close_(); + // A forgotten network no longer has a valid GUID, close the subpage. + this.close_(); }, /** @private */
diff --git a/chrome/browser/resources/settings/people_page/setup_pin_dialog.html b/chrome/browser/resources/settings/people_page/setup_pin_dialog.html index 50d933aa7..3713f67 100644 --- a/chrome/browser/resources/settings/people_page/setup_pin_dialog.html +++ b/chrome/browser/resources/settings/people_page/setup_pin_dialog.html
@@ -1,3 +1,4 @@ +<link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
diff --git a/chrome/browser/resources/settings/people_page/setup_pin_dialog.js b/chrome/browser/resources/settings/people_page/setup_pin_dialog.js index 28748c0..428b5ae 100644 --- a/chrome/browser/resources/settings/people_page/setup_pin_dialog.js +++ b/chrome/browser/resources/settings/people_page/setup_pin_dialog.js
@@ -16,14 +16,21 @@ 'use strict'; /** - * A list of the top-10 most commmonly used PINs. This list is taken from - * www.datagenetics.com/blog/september32012/. - * @const + * Keep in sync with the string keys provided by settings. + * @enum {string} */ -var WEAK_PINS = [ - '1234', '1111', '0000', '1212', '7777', '1004', '2000', '4444', '2222', - '6969' -]; +var MessageType = { + TOO_SHORT: 'configurePinTooShort', + TOO_LONG: 'configurePinTooLong', + TOO_WEAK: 'configurePinWeakPin', + MISMATCH: 'configurePinMismatched' +}; + +/** @enum {string} */ +var ProblemType = { + WARNING: 'warning', + ERROR: 'error' +}; Polymer({ is: 'settings-setup-pin-dialog', @@ -80,6 +87,15 @@ type: Boolean, value: false }, + + /** + * Interface for chrome.quickUnlockPrivate calls. May be overriden by tests. + * @private + */ + quickUnlockPrivate_: { + type: Object, + value: chrome.quickUnlockPrivate + }, }, /** @override */ @@ -108,6 +124,7 @@ this.pinKeyboardValue_ = ''; this.enableSubmit_ = false; this.isConfirmStep_ = false; + this.hideProblem_(); this.onPinChange_(); }, @@ -118,49 +135,38 @@ }, /** - * Returns true if the given PIN is likely easy to guess. + * Returns true if the PIN is ready to be changed to a new value. * @private - * @param {string} pin * @return {boolean} */ - isPinWeak_: function(pin) { - // Warn if it's a top-10 pin. - if (WEAK_PINS.includes(pin)) - return true; + canSubmit_: function() { + return this.initialPin_ == this.pinKeyboardValue_; + }, - // Warn if the PIN is consecutive digits. - var delta = 0; - for (var i = 1; i < pin.length; ++i) { - var prev = Number(pin[i - 1]); - var num = Number(pin[i]); - if (Number.isNaN(prev) || Number.isNaN(num)) - return false; - delta = Math.max(delta, Math.abs(num - prev)); + /** + * Handles writting the appropriate message to |problemMessage_|. + * @private + * @param {string} messageId + * @param {chrome.quickUnlockPrivate.CredentialRequirements} requirements + * The requirements received from getCredentialRequirements. + */ + processPinRequirements_: function(messageId, requirements) { + var additionalInformation = ''; + switch (messageId) { + case MessageType.TOO_SHORT: + additionalInformation = requirements.minLength.toString(); + break; + case MessageType.TOO_LONG: + additionalInformation = requirements.maxLength.toString(); + break; + case MessageType.TOO_WEAK: + case MessageType.MISMATCH: + break; + default: + assertNotReached(); + break; } - - return delta <= 1; - }, - - /** - * Returns true if the given PIN matches PIN requirements, such as minimum - * length. - * @private - * @param {string|undefined} pin - * @return {boolean} - */ - isPinLongEnough_: function(pin) { - return !!pin && pin.length >= 4; - }, - - /** - * Returns true if the currently entered PIN is the same as the initially - * submitted PIN. - * @private - * @return {boolean} - */ - isPinConfirmed_: function() { - return this.isPinLongEnough_(this.pinKeyboardValue_) && - this.initialPin_ == this.pinKeyboardValue_; + this.problemMessage_ = this.i18n(messageId, additionalInformation); }, /** @@ -170,17 +176,14 @@ * @param {string} problemClass */ showProblem_: function(messageId, problemClass) { - var previousMessage = this.problemMessage_; - - // Update problem info. - this.problemMessage_ = this.i18n(messageId); + this.quickUnlockPrivate_.getCredentialRequirements( + chrome.quickUnlockPrivate.QuickUnlockMode.PIN, + this.processPinRequirements_.bind(this, messageId)); this.problemClass_ = problemClass; this.updateStyles(); - - // If the problem message has changed, fire an alert. - if (previousMessage != this.problemMessage_) - this.$.problemDiv.setAttribute('role', 'alert'); - }, + this.enableSubmit_ = problemClass != ProblemType.ERROR && + messageId != MessageType.MISMATCH; + }, /** @private */ hideProblem_: function() { @@ -188,67 +191,100 @@ this.problemClass_ = ''; }, + /** + * Processes the message received from the quick unlock api and hides/shows + * the problem based on the message. + * @private + * @param {chrome.quickUnlockPrivate.CredentialCheck} message The message + * received from checkCredential. + */ + processPinProblems_: function(message) { + if (!message.errors.length && !message.warnings.length) { + this.hideProblem_(); + this.enableSubmit_ = true; + return; + } + + if (message.warnings.length) { + assert(message.warnings[0] == + chrome.quickUnlockPrivate.CredentialProblem.TOO_WEAK); + this.showProblem_(MessageType.TOO_WEAK, ProblemType.WARNING); + } + + if (message.errors.length) { + switch (message.errors[0]) { + case chrome.quickUnlockPrivate.CredentialProblem.TOO_SHORT: + this.showProblem_(MessageType.TOO_SHORT, ProblemType.ERROR); + break; + case chrome.quickUnlockPrivate.CredentialProblem.TOO_LONG: + this.showProblem_(MessageType.TOO_LONG, ProblemType.ERROR); + break; + case chrome.quickUnlockPrivate.CredentialProblem.TOO_WEAK: + this.showProblem_(MessageType.TOO_WEAK, ProblemType.ERROR); + break; + default: + assertNotReached(); + break; + } + } + + }, + /** @private */ onPinChange_: function() { if (!this.isConfirmStep_) { - var isPinLongEnough = this.isPinLongEnough_(this.pinKeyboardValue_); - var isWeak = isPinLongEnough && this.isPinWeak_(this.pinKeyboardValue_); - - if (!isPinLongEnough) - this.showProblem_('configurePinTooShort', 'warning'); - else if (isWeak) - this.showProblem_('configurePinWeakPin', 'warning'); - else - this.hideProblem_(); - - this.enableSubmit_ = isPinLongEnough; - - } else { - if (this.isPinConfirmed_()) - this.hideProblem_(); - else - this.showProblem_('configurePinMismatched', 'warning'); - - this.enableSubmit_ = true; + if (this.pinKeyboardValue_) { + this.quickUnlockPrivate_.checkCredential( + chrome.quickUnlockPrivate.QuickUnlockMode.PIN, + this.pinKeyboardValue_, + this.processPinProblems_.bind(this)); + } + return; } + + if (this.canSubmit_()) { + this.hideProblem_(); + this.enableSubmit_ = true; + return; + } + + this.showProblem_(MessageType.MISMATCH, ProblemType.WARNING); }, /** @private */ onPinSubmit_: function() { if (!this.isConfirmStep_) { - if (this.isPinLongEnough_(this.pinKeyboardValue_)) { - this.initialPin_ = this.pinKeyboardValue_; - this.pinKeyboardValue_ = ''; - this.isConfirmStep_ = true; - this.onPinChange_(); - this.$.pinKeyboard.focus(); - this.writeUma_(LockScreenProgress.ENTER_PIN); - } - } else { - // onPinSubmit_ gets called if the user hits enter on the PIN keyboard. - // The PIN is not guaranteed to be valid in that case. - if (!this.isPinConfirmed_()) { - this.showProblem_('configurePinMismatched', 'error'); + this.initialPin_ = this.pinKeyboardValue_; + this.pinKeyboardValue_ = ''; + this.isConfirmStep_ = true; + this.onPinChange_(); + this.$.pinKeyboard.focus(); + this.writeUma_(LockScreenProgress.ENTER_PIN); + return; + } + // onPinSubmit_ gets called if the user hits enter on the PIN keyboard. + // The PIN is not guaranteed to be valid in that case. + if (!this.canSubmit_()) { + this.showProblem_(MessageType.MISMATCH, ProblemType.ERROR); + return; + } + + function onSetModesCompleted(didSet) { + if (!didSet) { + console.error('Failed to update pin'); return; } - function onSetModesCompleted(didSet) { - if (!didSet) { - console.error('Failed to update pin'); - return; - } - - this.resetState_(); - this.fire('done'); - } - - this.setModes.call( - null, - [chrome.quickUnlockPrivate.QuickUnlockMode.PIN], - [this.pinKeyboardValue_], - onSetModesCompleted.bind(this)); - this.writeUma_(LockScreenProgress.CONFIRM_PIN); + this.resetState_(); + this.fire('done'); } + + this.setModes.call( + null, + [chrome.quickUnlockPrivate.QuickUnlockMode.PIN], + [this.pinKeyboardValue_], + onSetModesCompleted.bind(this)); + this.writeUma_(LockScreenProgress.CONFIRM_PIN); }, /**
diff --git a/chrome/browser/themes/theme_service_win.cc b/chrome/browser/themes/theme_service_win.cc index defcb63..e556783 100644 --- a/chrome/browser/themes/theme_service_win.cc +++ b/chrome/browser/themes/theme_service_win.cc
@@ -43,12 +43,28 @@ if (id == ThemeProperties::COLOR_ACCENT_BORDER) return dwm_accent_border_color_; - if (use_dwm_frame_color_) { - // Incognito frame is the same as normal when we're using DWM colors. - if (id == ThemeProperties::COLOR_FRAME) - return dwm_frame_color_; - if (id == ThemeProperties::COLOR_FRAME_INACTIVE) - return dwm_inactive_frame_color_; + // When we're custom-drawing the titlebar we want to use either the colors + // we calculated in OnDwmKeyUpdated() or the default colors. When we're not + // custom-drawing the titlebar we want to match the color Windows actually + // uses because some things (like the incognito icon) use this color to + // decide whether they should draw in light or dark mode. Incognito colors + // should be the same as non-incognito in all cases here. + if (id == ThemeProperties::COLOR_FRAME) { + if (dwm_frame_color_) + return dwm_frame_color_.value(); + if (!ShouldCustomDrawSystemTitlebar()) + return SK_ColorWHITE; + // Fall through and use default. + } + if (id == ThemeProperties::COLOR_FRAME_INACTIVE) { + if (!ShouldCustomDrawSystemTitlebar()) { + return inactive_frame_color_from_registry_ + ? dwm_inactive_frame_color_.value() + : SK_ColorWHITE; + } + if (dwm_inactive_frame_color_) + return dwm_inactive_frame_color_.value(); + // Fall through and use default. } } @@ -62,25 +78,30 @@ void ThemeServiceWin::OnDwmKeyUpdated() { DWORD accent_color, color_prevalence; - use_dwm_frame_color_ = + bool use_dwm_frame_color = dwm_key_->ReadValueDW(L"AccentColor", &accent_color) == ERROR_SUCCESS && dwm_key_->ReadValueDW(L"ColorPrevalence", &color_prevalence) == ERROR_SUCCESS && color_prevalence == 1; - if (use_dwm_frame_color_) { + inactive_frame_color_from_registry_ = false; + if (use_dwm_frame_color) { dwm_frame_color_ = skia::COLORREFToSkColor(accent_color); DWORD accent_color_inactive; if (dwm_key_->ReadValueDW(L"AccentColorInactive", &accent_color_inactive) == ERROR_SUCCESS) { dwm_inactive_frame_color_ = skia::COLORREFToSkColor(accent_color_inactive); + inactive_frame_color_from_registry_ = true; } else { // Tint to create inactive color. Always use the non-incognito version of // the tint, since the frame should look the same in both modes. dwm_inactive_frame_color_ = color_utils::HSLShift( - dwm_frame_color_, + dwm_frame_color_.value(), GetTint(ThemeProperties::TINT_FRAME_INACTIVE, false)); } + } else { + dwm_frame_color_.reset(); + dwm_inactive_frame_color_.reset(); } dwm_accent_border_color_ = SK_ColorWHITE;
diff --git a/chrome/browser/themes/theme_service_win.h b/chrome/browser/themes/theme_service_win.h index de91fc6..6ea367f1 100644 --- a/chrome/browser/themes/theme_service_win.h +++ b/chrome/browser/themes/theme_service_win.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_THEMES_THEME_SERVICE_WIN_H_ #define CHROME_BROWSER_THEMES_THEME_SERVICE_WIN_H_ +#include "base/optional.h" #include "base/win/registry.h" #include "chrome/browser/themes/theme_service.h" @@ -33,15 +34,15 @@ // Registry key containing the params that determine the DWM frame color. std::unique_ptr<base::win::RegKey> dwm_key_; - // True if the frame should be colored using the DWM values here. False if the - // default frame colors should be used instead. - bool use_dwm_frame_color_; + // The frame color when active. If empty the default colors should be used. + base::Optional<SkColor> dwm_frame_color_; - // The frame color when active. - SkColor dwm_frame_color_; + // True if we took dwm_inactive_frame_color_ from the registry (vs calculating + // it ourselves) and thus Windows will use it too. + bool inactive_frame_color_from_registry_; - // The frame color when inactive. - SkColor dwm_inactive_frame_color_; + // The frame color when inactive. If empty the default colors should be used. + base::Optional<SkColor> dwm_inactive_frame_color_; // The DWM accent border color, if available; white otherwise. SkColor dwm_accent_border_color_;
diff --git a/chrome/browser/ui/cocoa/extensions/browser_action_button_interactive_uitest.mm b/chrome/browser/ui/cocoa/extensions/browser_action_button_interactive_uitest.mm index e1163f7..594fe1a 100644 --- a/chrome/browser/ui/cocoa/extensions/browser_action_button_interactive_uitest.mm +++ b/chrome/browser/ui/cocoa/extensions/browser_action_button_interactive_uitest.mm
@@ -29,6 +29,8 @@ #include "chrome/browser/ui/global_error/global_error.h" #include "chrome/browser/ui/global_error/global_error_service.h" #include "chrome/browser/ui/global_error/global_error_service_factory.h" +#include "chrome/browser/ui/toolbar/component_toolbar_actions_factory.h" +#include "chrome/browser/ui/toolbar/media_router_action.h" #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h" #include "chrome/browser/ui/toolbar/toolbar_actions_model.h" #include "chrome/test/base/interactive_test_utils.h" @@ -92,6 +94,35 @@ runLoop.Run(); } +// Simulates a click on the action button in the overflow menu, and runs +// |closure| upon completion. +void ClickOnOverflowedAction(ToolbarController* toolbarController, + const base::Closure& closure) { + AppMenuController* appMenuController = [toolbarController appMenuController]; + // The app menu should start as open (since that's where the overflowed + // actions are). + EXPECT_TRUE([appMenuController isMenuOpen]); + BrowserActionsController* overflowController = + [appMenuController browserActionsController]; + + ASSERT_TRUE(overflowController); + BrowserActionButton* actionButton = [overflowController buttonWithIndex:0]; + // The action should be attached to a superview. + EXPECT_TRUE([actionButton superview]); + + // ui_controls:: methods don't play nice when there is an open menu (like the + // app menu). Instead, simulate a right click by feeding the event directly to + // the button. + NSPoint centerPoint = GetCenterPoint(actionButton); + NSEvent* mouseEvent = cocoa_test_event_utils::RightMouseDownAtPointInWindow( + centerPoint, [actionButton window]); + [actionButton rightMouseDown:mouseEvent]; + + // This should close the app menu. + EXPECT_FALSE([appMenuController isMenuOpen]); + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, closure); +} + } // namespace // A simple helper menu delegate that will keep track of if a menu is opened, @@ -229,6 +260,35 @@ ExtensionBrowserTest::TearDownOnMainThread(); } + // Opens the app menu and the context menu of the overflowed action, and + // checks that the menus get opened/closed properly. |menuHelper| must be set + // as the delegate for the context menu. + void OpenAppMenuAndActionContextMenu(MenuHelper* menuHelper) { + // Move the mouse over the app menu button. + MoveMouseToCenter(appMenuButton()); + + // No menu yet (on the browser action). + EXPECT_FALSE([menuHelper menuOpened]); + base::RunLoop runLoop; + // Click on the app menu, and pass in a callback to continue the test in + // ClickOnOverflowedAction. Due to the blocking nature of Cocoa menus, we + // can't test the menu synchronously here by quitting the run loop when it + // opens, and instead need to test through a callback. + base::scoped_nsobject<MenuWatcher> menuWatcher( + [[MenuWatcher alloc] initWithController:appMenuController()]); + [menuWatcher + setOpenClosure:base::Bind(&ClickOnOverflowedAction, + base::Unretained(toolbarController()), + runLoop.QuitClosure())]; + ui_controls::SendMouseEvents(ui_controls::LEFT, + ui_controls::DOWN | ui_controls::UP); + runLoop.Run(); + + // The menu opened on the main bar's action button rather than the + // overflow's since Cocoa does not support running a menu within a menu. + EXPECT_TRUE([menuHelper menuOpened]); + } + ToolbarController* toolbarController() { return toolbarController_; } AppMenuController* appMenuController() { return appMenuController_; } ToolbarActionsModel* model() { return model_; } @@ -244,37 +304,6 @@ DISALLOW_COPY_AND_ASSIGN(BrowserActionButtonUiTest); }; -// Simulates a clicks on the action button in the overflow menu, and runs -// |closure| upon completion. -void ClickOnOverflowedAction(ToolbarController* toolbarController, - const base::Closure& closure) { - AppMenuController* appMenuController = - [toolbarController appMenuController]; - // The app menu should start as open (since that's where the overflowed - // actions are). - EXPECT_TRUE([appMenuController isMenuOpen]); - BrowserActionsController* overflowController = - [appMenuController browserActionsController]; - - ASSERT_TRUE(overflowController); - BrowserActionButton* actionButton = - [overflowController buttonWithIndex:0]; - // The action should be attached to a superview. - EXPECT_TRUE([actionButton superview]); - - // ui_controls:: methods don't play nice when there is an open menu (like the - // app menu). Instead, simulate a right click by feeding the event directly to - // the button. - NSPoint centerPoint = GetCenterPoint(actionButton); - NSEvent* mouseEvent = cocoa_test_event_utils::RightMouseDownAtPointInWindow( - centerPoint, [actionButton window]); - [actionButton rightMouseDown:mouseEvent]; - - // This should close the app menu. - EXPECT_FALSE([appMenuController isMenuOpen]); - base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, closure); -} - // Verifies that the action is "popped out" of overflow; that is, it is visible // on the main bar, and is set as the popped out action on the controlling // ToolbarActionsBar. @@ -342,32 +371,37 @@ model()->SetVisibleIconCount(0); EXPECT_EQ(nil, [actionButton superview]); - // Move the mouse over the app menu button. - MoveMouseToCenter(appMenuButton()); + OpenAppMenuAndActionContextMenu(menuHelper.get()); +} - { - // No menu yet (on the browser action). - EXPECT_FALSE([menuHelper menuOpened]); - base::RunLoop runLoop; - // Click on the app menu, and pass in a callback to continue the test in - // ClickOnOverflowedAction (Due to the blocking nature of Cocoa menus, - // passing in runLoop.QuitClosure() is not sufficient here.) - base::scoped_nsobject<MenuWatcher> menuWatcher( - [[MenuWatcher alloc] initWithController:appMenuController()]); - [menuWatcher setOpenClosure: - base::Bind(&ClickOnOverflowedAction, - base::Unretained(toolbarController()), - runLoop.QuitClosure())]; - ui_controls::SendMouseEvents(ui_controls::LEFT, - ui_controls::DOWN | ui_controls::UP); - runLoop.Run(); +IN_PROC_BROWSER_TEST_F(BrowserActionButtonUiTest, + MediaRouterActionContextMenuInOverflow) { + model()->AddComponentAction( + ComponentToolbarActionsFactory::kMediaRouterActionId); + ASSERT_EQ(1u, model()->toolbar_items().size()); - // The menu should have opened. Note that the menu opened on the main bar's - // action button, not the overflow's. Since Cocoa doesn't support running - // a menu-within-a-menu, this is what has to happen. - EXPECT_TRUE([menuHelper menuOpened]); - EXPECT_FALSE([actionButton isHighlighted]); - } + BrowserActionButton* actionButton = + [[toolbarController() browserActionsController] buttonWithIndex:0]; + ASSERT_TRUE(actionButton); + + // Stub out the action button's normal context menu with a fake one so we + // can track when it opens. + base::scoped_nsobject<NSMenu> testContextMenu( + [[NSMenu alloc] initWithTitle:@""]); + base::scoped_nsobject<MenuHelper> menuHelper([[MenuHelper alloc] init]); + [testContextMenu setDelegate:menuHelper.get()]; + [actionButton setTestContextMenu:testContextMenu.get()]; + + model()->SetActionVisibility( + ComponentToolbarActionsFactory::kMediaRouterActionId, false); + + OpenAppMenuAndActionContextMenu(menuHelper.get()); + + ToolbarActionsBar* actionsBar = + [[toolbarController() browserActionsController] toolbarActionsBar]; + // The action should be back in the overflow. + EXPECT_FALSE( + actionsBar->IsActionVisibleOnMainBar(actionsBar->GetActions()[0])); } // Checks the layout of the overflow bar in the app menu.
diff --git a/chrome/browser/ui/toolbar/media_router_action.cc b/chrome/browser/ui/toolbar/media_router_action.cc index d9b7850c..ed5d6969 100644 --- a/chrome/browser/ui/toolbar/media_router_action.cc +++ b/chrome/browser/ui/toolbar/media_router_action.cc
@@ -138,6 +138,13 @@ return contextual_menu_.menu_model(); } +void MediaRouterAction::OnContextMenuClosed() { + if (toolbar_actions_bar_->popped_out_action() == this && + !GetMediaRouterDialogController()->IsShowingMediaRouterDialog()) { + toolbar_actions_bar_->UndoPopOut(); + } +} + bool MediaRouterAction::ExecuteAction(bool by_user) { base::RecordAction(base::UserMetricsAction("MediaRouter_Icon_Click"));
diff --git a/chrome/browser/ui/toolbar/media_router_action.h b/chrome/browser/ui/toolbar/media_router_action.h index 14564a5..ec88162 100644 --- a/chrome/browser/ui/toolbar/media_router_action.h +++ b/chrome/browser/ui/toolbar/media_router_action.h
@@ -56,6 +56,7 @@ void HidePopup() override; gfx::NativeView GetPopupNativeView() override; ui::MenuModel* GetContextMenu() override; + void OnContextMenuClosed() override; bool ExecuteAction(bool by_user) override; void UpdateState() override; bool DisabledClickOpensMenu() const override;
diff --git a/chrome/browser/ui/views/certificate_selector.cc b/chrome/browser/ui/views/certificate_selector.cc index f3397ded..9c7381f 100644 --- a/chrome/browser/ui/views/certificate_selector.cc +++ b/chrome/browser/ui/views/certificate_selector.cc
@@ -223,7 +223,7 @@ ui::TableColumn::LEFT, -1, 0.2f)); table_ = new views::TableView(model_.get(), columns, views::TEXT_ONLY, true /* single_selection */); - table_->SetObserver(this); + table_->set_observer(this); layout->StartRow(1, kColumnSetId); layout->AddView(table_->CreateParentIfNecessary(), 1, 1, views::GridLayout::FILL, views::GridLayout::FILL,
diff --git a/chrome/browser/ui/views/chooser_content_view.cc b/chrome/browser/ui/views/chooser_content_view.cc index 1c05f1b..0310f30 100644 --- a/chrome/browser/ui/views/chooser_content_view.cc +++ b/chrome/browser/ui/views/chooser_content_view.cc
@@ -66,7 +66,7 @@ : views::TEXT_ONLY, !chooser_controller_->AllowMultipleSelection() /* single_selection */); table_view_->set_select_on_remove(false); - table_view_->SetObserver(table_view_observer); + table_view_->set_observer(table_view_observer); table_view_->SetEnabled(chooser_controller_->NumOptions() > 0); table_parent_ = table_view_->CreateParentIfNecessary(); @@ -91,7 +91,7 @@ ChooserContentView::~ChooserContentView() { chooser_controller_->set_view(nullptr); - table_view_->SetObserver(nullptr); + table_view_->set_observer(nullptr); table_view_->SetModel(nullptr); }
diff --git a/chrome/browser/ui/views/chooser_content_view_unittest.cc b/chrome/browser/ui/views/chooser_content_view_unittest.cc index cd8456b..dbfd1539 100644 --- a/chrome/browser/ui/views/chooser_content_view_unittest.cc +++ b/chrome/browser/ui/views/chooser_content_view_unittest.cc
@@ -14,6 +14,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/base/models/list_selection_model.h" #include "ui/views/controls/link.h" #include "ui/views/controls/styled_label.h" #include "ui/views/controls/table/table_view.h" @@ -89,7 +90,7 @@ // |table_view_| should be disabled since there is no option shown. EXPECT_FALSE(table_view_->enabled()); // No option selected. - EXPECT_EQ(0, table_view_->SelectedRowCount()); + EXPECT_EQ(0UL, table_view_->selection_model().size()); EXPECT_EQ(-1, table_view_->FirstSelectedRow()); EXPECT_FALSE(throbber_->visible()); EXPECT_FALSE(turn_adapter_off_help_->visible()); @@ -109,7 +110,7 @@ // |table_view_| should be enabled since there is an option. EXPECT_TRUE(table_view_->enabled()); // No option selected. - EXPECT_EQ(0, table_view_->SelectedRowCount()); + EXPECT_EQ(0UL, table_view_->selection_model().size()); EXPECT_EQ(-1, table_view_->FirstSelectedRow()); mock_chooser_controller_->OptionAdded( @@ -118,7 +119,7 @@ EXPECT_EQ(2, table_view_->RowCount()); EXPECT_EQ(base::ASCIIToUTF16("b"), table_model_->GetText(1, 0)); EXPECT_TRUE(table_view_->enabled()); - EXPECT_EQ(0, table_view_->SelectedRowCount()); + EXPECT_EQ(0UL, table_view_->selection_model().size()); EXPECT_EQ(-1, table_view_->FirstSelectedRow()); mock_chooser_controller_->OptionAdded( @@ -127,7 +128,7 @@ EXPECT_EQ(3, table_view_->RowCount()); EXPECT_EQ(base::ASCIIToUTF16("c"), table_model_->GetText(2, 0)); EXPECT_TRUE(table_view_->enabled()); - EXPECT_EQ(0, table_view_->SelectedRowCount()); + EXPECT_EQ(0UL, table_view_->selection_model().size()); EXPECT_EQ(-1, table_view_->FirstSelectedRow()); } @@ -152,7 +153,7 @@ EXPECT_EQ(GetPairedText("a"), table_model_->GetText(0, 0)); EXPECT_EQ(base::ASCIIToUTF16("c"), table_model_->GetText(1, 0)); EXPECT_TRUE(table_view_->enabled()); - EXPECT_EQ(0, table_view_->SelectedRowCount()); + EXPECT_EQ(0UL, table_view_->selection_model().size()); EXPECT_EQ(-1, table_view_->FirstSelectedRow()); // Remove a non-existent option, the number of rows should not change. @@ -161,14 +162,14 @@ EXPECT_EQ(GetPairedText("a"), table_model_->GetText(0, 0)); EXPECT_EQ(base::ASCIIToUTF16("c"), table_model_->GetText(1, 0)); EXPECT_TRUE(table_view_->enabled()); - EXPECT_EQ(0, table_view_->SelectedRowCount()); + EXPECT_EQ(0UL, table_view_->selection_model().size()); EXPECT_EQ(-1, table_view_->FirstSelectedRow()); mock_chooser_controller_->OptionRemoved(base::ASCIIToUTF16("c")); EXPECT_EQ(1, table_view_->RowCount()); EXPECT_EQ(GetPairedText("a"), table_model_->GetText(0, 0)); EXPECT_TRUE(table_view_->enabled()); - EXPECT_EQ(0, table_view_->SelectedRowCount()); + EXPECT_EQ(0UL, table_view_->selection_model().size()); EXPECT_EQ(-1, table_view_->FirstSelectedRow()); mock_chooser_controller_->OptionRemoved(base::ASCIIToUTF16("a")); @@ -180,7 +181,7 @@ table_model_->GetText(0, 0)); // |table_view_| should be disabled since all options are removed. EXPECT_FALSE(table_view_->enabled()); - EXPECT_EQ(0, table_view_->SelectedRowCount()); + EXPECT_EQ(0UL, table_view_->selection_model().size()); EXPECT_EQ(-1, table_view_->FirstSelectedRow()); } @@ -209,7 +210,7 @@ EXPECT_EQ(GetPairedText("d"), table_model_->GetText(1, 0)); EXPECT_EQ(base::ASCIIToUTF16("c"), table_model_->GetText(2, 0)); EXPECT_TRUE(table_view_->enabled()); - EXPECT_EQ(0, table_view_->SelectedRowCount()); + EXPECT_EQ(0UL, table_view_->selection_model().size()); EXPECT_EQ(-1, table_view_->FirstSelectedRow()); } @@ -271,7 +272,7 @@ EXPECT_EQ(GetPairedText("a"), table_model_->GetText(0, 0)); EXPECT_EQ(base::ASCIIToUTF16("c"), table_model_->GetText(1, 0)); EXPECT_TRUE(table_view_->enabled()); - EXPECT_EQ(0, table_view_->SelectedRowCount()); + EXPECT_EQ(0UL, table_view_->selection_model().size()); EXPECT_EQ(-1, table_view_->FirstSelectedRow()); } @@ -292,22 +293,22 @@ // Select option 0. table_view_->Select(0); - EXPECT_EQ(1, table_view_->SelectedRowCount()); + EXPECT_EQ(1UL, table_view_->selection_model().size()); EXPECT_EQ(0, table_view_->FirstSelectedRow()); // Unselect option 0. table_view_->Select(-1); - EXPECT_EQ(0, table_view_->SelectedRowCount()); + EXPECT_EQ(0UL, table_view_->selection_model().size()); EXPECT_EQ(-1, table_view_->FirstSelectedRow()); // Select option 1. table_view_->Select(1); - EXPECT_EQ(1, table_view_->SelectedRowCount()); + EXPECT_EQ(1UL, table_view_->selection_model().size()); EXPECT_EQ(1, table_view_->FirstSelectedRow()); // Unselect option 1. table_view_->Select(-1); - EXPECT_EQ(0, table_view_->SelectedRowCount()); + EXPECT_EQ(0UL, table_view_->selection_model().size()); EXPECT_EQ(-1, table_view_->FirstSelectedRow()); } @@ -328,17 +329,17 @@ // Select option 0. table_view_->Select(0); - EXPECT_EQ(1, table_view_->SelectedRowCount()); + EXPECT_EQ(1UL, table_view_->selection_model().size()); EXPECT_EQ(0, table_view_->FirstSelectedRow()); // Select option 1. table_view_->Select(1); - EXPECT_EQ(1, table_view_->SelectedRowCount()); + EXPECT_EQ(1UL, table_view_->selection_model().size()); EXPECT_EQ(1, table_view_->FirstSelectedRow()); // Select option 2. table_view_->Select(2); - EXPECT_EQ(1, table_view_->SelectedRowCount()); + EXPECT_EQ(1UL, table_view_->selection_model().size()); EXPECT_EQ(2, table_view_->FirstSelectedRow()); } @@ -361,13 +362,13 @@ // Select option 1. table_view_->Select(1); - EXPECT_EQ(1, table_view_->SelectedRowCount()); + EXPECT_EQ(1UL, table_view_->selection_model().size()); EXPECT_EQ(1, table_view_->FirstSelectedRow()); // Remove option 0, the list becomes: b c. mock_chooser_controller_->OptionRemoved(base::ASCIIToUTF16("a")); EXPECT_EQ(2, table_view_->RowCount()); - EXPECT_EQ(1, table_view_->SelectedRowCount()); + EXPECT_EQ(1UL, table_view_->selection_model().size()); // Since option 0 is removed, the original selected option 1 becomes // the first option in the list. EXPECT_EQ(0, table_view_->FirstSelectedRow()); @@ -375,7 +376,7 @@ // Remove option 1. mock_chooser_controller_->OptionRemoved(base::ASCIIToUTF16("c")); EXPECT_EQ(1, table_view_->RowCount()); - EXPECT_EQ(1, table_view_->SelectedRowCount()); + EXPECT_EQ(1UL, table_view_->selection_model().size()); EXPECT_EQ(0, table_view_->FirstSelectedRow()); } @@ -396,14 +397,14 @@ // Select option 1. table_view_->Select(1); - EXPECT_EQ(1, table_view_->SelectedRowCount()); + EXPECT_EQ(1UL, table_view_->selection_model().size()); EXPECT_EQ(1, table_view_->FirstSelectedRow()); // Remove option 1. mock_chooser_controller_->OptionRemoved(base::ASCIIToUTF16("b")); EXPECT_EQ(2, table_view_->RowCount()); // No option selected. - EXPECT_EQ(0, table_view_->SelectedRowCount()); + EXPECT_EQ(0UL, table_view_->selection_model().size()); EXPECT_EQ(-1, table_view_->FirstSelectedRow()); } @@ -432,7 +433,7 @@ MockChooserController::ConnectedPairedStatus::CONNECTED | MockChooserController::ConnectedPairedStatus::PAIRED); - EXPECT_EQ(1, table_view_->SelectedRowCount()); + EXPECT_EQ(1UL, table_view_->selection_model().size()); EXPECT_EQ(1, table_view_->FirstSelectedRow()); EXPECT_EQ(GetPairedText("a"), table_model_->GetText(0, 0)); EXPECT_EQ(GetPairedText("d"), table_model_->GetText(1, 0)); @@ -451,7 +452,7 @@ // Select option 0. table_view_->Select(0); - EXPECT_EQ(1, table_view_->SelectedRowCount()); + EXPECT_EQ(1UL, table_view_->selection_model().size()); EXPECT_EQ(0, table_view_->FirstSelectedRow()); // Remove option 0. @@ -465,7 +466,7 @@ // |table_view_| should be disabled since all options are removed. EXPECT_FALSE(table_view_->enabled()); // No option selected. - EXPECT_EQ(0, table_view_->SelectedRowCount()); + EXPECT_EQ(0UL, table_view_->selection_model().size()); EXPECT_EQ(-1, table_view_->FirstSelectedRow()); } @@ -484,7 +485,7 @@ // |table_view_| should be disabled since there is no option shown. EXPECT_FALSE(table_view_->enabled()); // No option selected. - EXPECT_EQ(0, table_view_->SelectedRowCount()); + EXPECT_EQ(0UL, table_view_->selection_model().size()); EXPECT_EQ(-1, table_view_->FirstSelectedRow()); EXPECT_FALSE(throbber_->visible()); EXPECT_FALSE(turn_adapter_off_help_->visible()); @@ -522,7 +523,7 @@ l10n_util::GetStringUTF16(IDS_DEVICE_CHOOSER_NO_DEVICES_FOUND_PROMPT), table_model_->GetText(0, 0)); EXPECT_FALSE(table_view_->enabled()); - EXPECT_EQ(0, table_view_->SelectedRowCount()); + EXPECT_EQ(0UL, table_view_->selection_model().size()); EXPECT_EQ(-1, table_view_->FirstSelectedRow()); EXPECT_FALSE(throbber_->visible()); EXPECT_FALSE(turn_adapter_off_help_->visible()); @@ -565,7 +566,7 @@ // |table_view_| should be disabled since there is no option shown. EXPECT_FALSE(table_view_->enabled()); // No option selected. - EXPECT_EQ(0, table_view_->SelectedRowCount()); + EXPECT_EQ(0UL, table_view_->selection_model().size()); EXPECT_EQ(-1, table_view_->FirstSelectedRow()); EXPECT_FALSE(throbber_->visible()); EXPECT_EQ(chooser_content_view_->help_and_re_scan_text_, @@ -599,13 +600,13 @@ // |table_view_| should be enabled since there is an option. EXPECT_TRUE(table_view_->enabled()); // No option selected. - EXPECT_EQ(0, table_view_->SelectedRowCount()); + EXPECT_EQ(0UL, table_view_->selection_model().size()); EXPECT_EQ(-1, table_view_->FirstSelectedRow()); EXPECT_FALSE(throbber_->visible()); EXPECT_EQ(chooser_content_view_->help_and_scanning_text_, footnote_link_->text()); table_view_->Select(0); - EXPECT_EQ(1, table_view_->SelectedRowCount()); + EXPECT_EQ(1UL, table_view_->selection_model().size()); EXPECT_EQ(0, table_view_->FirstSelectedRow()); mock_chooser_controller_->OnDiscoveryStateChanged( @@ -615,7 +616,7 @@ EXPECT_EQ(base::ASCIIToUTF16("d"), table_model_->GetText(0, 0)); // |table_view_| should be enabled since there is an option. EXPECT_TRUE(table_view_->enabled()); - EXPECT_EQ(1, table_view_->SelectedRowCount()); + EXPECT_EQ(1UL, table_view_->selection_model().size()); EXPECT_EQ(0, table_view_->FirstSelectedRow()); EXPECT_FALSE(throbber_->visible()); EXPECT_EQ(chooser_content_view_->help_and_re_scan_text_,
diff --git a/chrome/browser/ui/views/task_manager_view.cc b/chrome/browser/ui/views/task_manager_view.cc index 4fa2e9c0..60717d7 100644 --- a/chrome/browser/ui/views/task_manager_view.cc +++ b/chrome/browser/ui/views/task_manager_view.cc
@@ -324,7 +324,7 @@ this)); tab_table_->SetModel(table_model_.get()); tab_table_->SetGrouper(this); - tab_table_->SetObserver(this); + tab_table_->set_observer(this); tab_table_->set_context_menu_controller(this); set_context_menu_controller(this);
diff --git a/chrome/browser/ui/views/task_manager_view_browsertest.cc b/chrome/browser/ui/views/task_manager_view_browsertest.cc index d6f996e..c45a7fd7 100644 --- a/chrome/browser/ui/views/task_manager_view_browsertest.cc +++ b/chrome/browser/ui/views/task_manager_view_browsertest.cc
@@ -207,13 +207,13 @@ // be selected. chrome::ShowTaskManager(browser()); - EXPECT_EQ(1, GetTable()->SelectedRowCount()); + EXPECT_EQ(1UL, GetTable()->selection_model().size()); EXPECT_EQ(GetTable()->FirstSelectedRow(), FindRowForTab(browser()->tab_strip_model()->GetWebContentsAt(1))); // Activate tab 0. The selection should not change. browser()->tab_strip_model()->ActivateTabAt(0, true); - EXPECT_EQ(1, GetTable()->SelectedRowCount()); + EXPECT_EQ(1UL, GetTable()->selection_model().size()); EXPECT_EQ(GetTable()->FirstSelectedRow(), FindRowForTab(browser()->tab_strip_model()->GetWebContentsAt(1))); @@ -221,7 +221,7 @@ // should set the TaskManager selection to the active tab. chrome::ShowTaskManager(browser()); - EXPECT_EQ(1, GetTable()->SelectedRowCount()); + EXPECT_EQ(1UL, GetTable()->selection_model().size()); EXPECT_EQ(GetTable()->FirstSelectedRow(), FindRowForTab(browser()->tab_strip_model()->GetWebContentsAt(0))); } @@ -267,7 +267,7 @@ // Select the middle row, and store its tab id. GetTable()->Select(FindRowForTab(tabs[1])); EXPECT_EQ(GetTable()->FirstSelectedRow(), FindRowForTab(tabs[1])); - EXPECT_EQ(1, GetTable()->SelectedRowCount()); + EXPECT_EQ(1UL, GetTable()->selection_model().size()); // Add 3 rows above the selection. The selected tab should not change. for (int i = 0; i < 3; ++i) { @@ -276,7 +276,7 @@ } ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows((rows += 3), pattern)); EXPECT_EQ(GetTable()->FirstSelectedRow(), FindRowForTab(tabs[1])); - EXPECT_EQ(1, GetTable()->SelectedRowCount()); + EXPECT_EQ(1UL, GetTable()->selection_model().size()); // Add 2 rows below the selection. The selected tab should not change. for (int i = 0; i < 2; ++i) { @@ -285,7 +285,7 @@ } ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows((rows += 2), pattern)); EXPECT_EQ(GetTable()->FirstSelectedRow(), FindRowForTab(tabs[1])); - EXPECT_EQ(1, GetTable()->SelectedRowCount()); + EXPECT_EQ(1UL, GetTable()->selection_model().size()); // Add a new row in the same process as the selection. The selected tab should // not change. @@ -293,7 +293,7 @@ EXPECT_EQ(GetTable()->FirstSelectedRow(), FindRowForTab(tabs[1])); ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows((rows += 1), pattern)); EXPECT_EQ(GetTable()->FirstSelectedRow(), FindRowForTab(tabs[1])); - EXPECT_EQ(1, GetTable()->SelectedRowCount()); + EXPECT_EQ(1UL, GetTable()->selection_model().size()); // Press the button, which kills the process of the selected row. PressKillButton();
diff --git a/chrome/browser/ui/webui/options/browser_options_handler.cc b/chrome/browser/ui/webui/options/browser_options_handler.cc index 77eb09d..d10d452 100644 --- a/chrome/browser/ui/webui/options/browser_options_handler.cc +++ b/chrome/browser/ui/webui/options/browser_options_handler.cc
@@ -516,6 +516,7 @@ IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_CONTINUE_BUTTON }, { "configurePinMismatched", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_MISMATCHED }, { "configurePinTooShort", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_TOO_SHORT} , + { "configurePinTooLong", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_TOO_LONG} , { "configurePinWeakPin", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_WEAK_PIN }, { "lockScreenChangePinButton", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_CHANGE_PIN_BUTTON},
diff --git a/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc b/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc index 4290d407..36a33031 100644 --- a/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc
@@ -82,6 +82,7 @@ ChangePictureHandler::ChangePictureHandler() : previous_image_url_(url::kAboutBlankURL), previous_image_index_(user_manager::User::USER_IMAGE_INVALID), + user_manager_observer_(this), camera_observer_(this) { ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); media::SoundsManager* manager = media::SoundsManager::Get(); @@ -116,14 +117,12 @@ } void ChangePictureHandler::OnJavascriptAllowed() { - user_manager::UserManager::Get()->AddObserver(this); - + user_manager_observer_.Add(user_manager::UserManager::Get()); camera_observer_.Add(CameraPresenceNotifier::GetInstance()); } void ChangePictureHandler::OnJavascriptDisallowed() { - user_manager::UserManager::Get()->RemoveObserver(this); - + user_manager_observer_.Remove(user_manager::UserManager::Get()); camera_observer_.Remove(CameraPresenceNotifier::GetInstance()); }
diff --git a/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h b/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h index 55e718b..a2132822 100644 --- a/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h +++ b/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h
@@ -126,6 +126,8 @@ // Data URL for |user_photo_|. std::string user_photo_data_url_; + ScopedObserver<user_manager::UserManager, ChangePictureHandler> + user_manager_observer_; ScopedObserver<CameraPresenceNotifier, ChangePictureHandler> camera_observer_; DISALLOW_COPY_AND_ASSIGN(ChangePictureHandler);
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index 12de100..67c9d72a 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -1068,6 +1068,7 @@ IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_CONTINUE_BUTTON}, {"configurePinMismatched", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_MISMATCHED}, {"configurePinTooShort", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_TOO_SHORT}, + {"configurePinTooLong", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_TOO_LONG}, {"configurePinWeakPin", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_WEAK_PIN}, {"enableScreenlock", IDS_SETTINGS_PEOPLE_ENABLE_SCREENLOCK}, {"lockScreenChangePinButton",
diff --git a/chrome/browser/ui/webui/settings/profile_info_handler.cc b/chrome/browser/ui/webui/settings/profile_info_handler.cc index 60f91128..4ce53d7 100644 --- a/chrome/browser/ui/webui/settings/profile_info_handler.cc +++ b/chrome/browser/ui/webui/settings/profile_info_handler.cc
@@ -41,6 +41,9 @@ ProfileInfoHandler::ProfileInfoHandler(Profile* profile) : profile_(profile), +#if defined(OS_CHROMEOS) + user_manager_observer_(this), +#endif profile_observer_(this) { #if defined(OS_CHROMEOS) // Set up the chrome://userimage/ source. @@ -79,7 +82,7 @@ base::Unretained(this))); #if defined(OS_CHROMEOS) - user_manager::UserManager::Get()->AddObserver(this); + user_manager_observer_.Add(user_manager::UserManager::Get()); #endif } @@ -90,7 +93,7 @@ profile_pref_registrar_.RemoveAll(); #if defined(OS_CHROMEOS) - user_manager::UserManager::Get()->RemoveObserver(this); + user_manager_observer_.Remove(user_manager::UserManager::Get()); #endif }
diff --git a/chrome/browser/ui/webui/settings/profile_info_handler.h b/chrome/browser/ui/webui/settings/profile_info_handler.h index c7919c4..6aa21f0 100644 --- a/chrome/browser/ui/webui/settings/profile_info_handler.h +++ b/chrome/browser/ui/webui/settings/profile_info_handler.h
@@ -16,8 +16,6 @@ #if defined(OS_CHROMEOS) #include "components/user_manager/user_manager.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" #else #include "chrome/browser/profiles/profile_statistics_common.h" #endif @@ -86,6 +84,11 @@ // Weak pointer. Profile* profile_; +#if defined(OS_CHROMEOS) + ScopedObserver<user_manager::UserManager, ProfileInfoHandler> + user_manager_observer_; +#endif + ScopedObserver<ProfileAttributesStorage, ProfileInfoHandler> profile_observer_;
diff --git a/chrome/test/data/extensions/api_test/tab_capture/fullscreen_test.js b/chrome/test/data/extensions/api_test/tab_capture/fullscreen_test.js index 7c54fe3..00897c0 100644 --- a/chrome/test/data/extensions/api_test/tab_capture/fullscreen_test.js +++ b/chrome/test/data/extensions/api_test/tab_capture/fullscreen_test.js
@@ -2,49 +2,77 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -window.addEventListener('load', function() { - document.body.onclick = function toggleBodyFullscreen() { +window.addEventListener('load', () => { + // Register the fullscreen change listener. This is used to determine when to + // signal the C++ side of this test that the document has entered/exited + // fullscreen. NOTE: It's very important NOT to use the + // tabCapture.onStatusChanged listener to signal the C++ side of this test + // because sometimes the document's fullscreen state change lags behind what + // the tabCapture API knows about the browser window's fullscreen state. + // Otherwise, the C++ side of this test might proceed out-of-sync and fail. + // http://crbug.com/675851 + if (document.fullscreenEnabled) { + document.onfullscreenchange = () => { + if (document.fullscreenElement) + chrome.test.sendMessage('entered_fullscreen'); + }; + } else if (document.webkitFullscreenEnabled) { + document.onwebkitfullscreenchange = () => { + if (document.webkitFullscreenElement) + chrome.test.sendMessage('entered_fullscreen'); + }; + } else { + chrome.test.assertTrue(!'HTML5 Fullscreen API missing'); + } + + // Register an onclick listener that toggles the entire document into or + // out-of fullscreen mode. The clicks are generated by the C++ side of this + // test. + document.documentElement.onclick = () => { if (document.fullscreenElement || document.webkitFullscreenElement) { if (document.exitFullscreen) document.exitFullscreen(); else if (document.webkitExitFullscreen) document.webkitExitFullscreen(); else - chrome.test.assertTrue(!"HTML5 Fullscreen API missing"); + chrome.test.assertTrue(!'HTML5 Fullscreen API missing'); } else { - if (document.body.requestFullscreen) - document.body.requestFullscreen(); - else if (document.body.webkitRequestFullscreen) - document.body.webkitRequestFullscreen(); + if (document.documentElement.requestFullscreen) + document.documentElement.requestFullscreen(); + else if (document.documentElement.webkitRequestFullscreen) + document.documentElement.webkitRequestFullscreen(); else - chrome.test.assertTrue(!"HTML5 Fullscreen API missing"); + chrome.test.assertTrue(!'HTML5 Fullscreen API missing'); } }; -}); -var mediaStream = null; -var events = []; + let mediaStream = null; + const events = []; -chrome.tabCapture.onStatusChanged.addListener(function(info) { - if (info.status == 'active') { - events.push(info.fullscreen); - if (events.length == 3) { - chrome.test.assertFalse(events[0]); - chrome.test.assertTrue(events[1]); - chrome.test.assertFalse(events[2]); - mediaStream.getVideoTracks()[0].stop(); - mediaStream.getAudioTracks()[0].stop(); - chrome.test.succeed(); + // Register the tab capture status change listener, which records the changes + // to fullscreen state according to the tab capture API implementation. Once + // there are three changes, check the results and succeed() the test. + chrome.tabCapture.onStatusChanged.addListener(info => { + if (info.status == 'active') { + events.push(info.fullscreen); + if (events.length == 3) { + mediaStream.getVideoTracks()[0].stop(); + mediaStream.getAudioTracks()[0].stop(); + chrome.test.assertFalse(events[0]); + chrome.test.assertTrue(events[1]); + chrome.test.assertFalse(events[2]); + chrome.test.succeed(); + } } + }); - if (info.fullscreen) - chrome.test.sendMessage('entered_fullscreen'); - } -}); - -chrome.tabCapture.capture({audio: true, video: true}, function(stream) { - chrome.test.assertTrue(!!stream); - mediaStream = stream; - chrome.test.notifyPass(); - chrome.test.sendMessage('tab_capture_started'); + // Now that all listeners are in-place, start tab capture. Once tab capture is + // running, notify the C++ side of this test that it may commence with the + // "fullscreen toggle mouse clicks." + chrome.tabCapture.capture({audio: true, video: true}, stream => { + chrome.test.assertTrue(!!stream); + mediaStream = stream; + chrome.test.notifyPass(); + chrome.test.sendMessage('tab_capture_started'); + }); });
diff --git a/chrome/test/data/webui/settings/fake_quick_unlock_private.js b/chrome/test/data/webui/settings/fake_quick_unlock_private.js index 0852d67..ae005e7 100644 --- a/chrome/test/data/webui/settings/fake_quick_unlock_private.js +++ b/chrome/test/data/webui/settings/fake_quick_unlock_private.js
@@ -5,6 +5,13 @@ /** * @fileoverview Fake implementation of chrome.quickUnlockPrivate for testing. */ + +/** + * A couple weak pins to use for testing. + * @const + */ +var TEST_WEAK_PINS = ['1111', '1234', '1313', '2001', '1010']; + cr.define('settings', function() { /** * Fake of the chrome.quickUnlockPrivate API. @@ -18,6 +25,8 @@ this.activeModes = []; /** @type {!Array<string>} */ this.credentials = []; /** @type {string} */ this.accountPassword = ''; + /** @type {!chrome.quickUnlockPrivate.CredentialRequirements} */ + this.credentialRequirements = {minLength: 4, maxLength: 0}; } FakeQuickUnlockPrivate.prototype = { @@ -54,7 +63,47 @@ this.activeModes = modes; this.credentials = credentials; onComplete(this.accountPassword == accountPassword); - } + }, + + /** + * @override + * @param {!chrome.quickUnlockPrivate.QuickUnlockMode} mode + * @param {string} credential + * @param {function( + * !chrome.quickUnlockPrivate.CredentialCheck):void} onComplete + */ + checkCredential: function(mode, credential, onComplete) { + var message = {}; + var errors = []; + var warnings = []; + + if (!!credential && + credential.length < this.credentialRequirements.minLength) { + errors.push(chrome.quickUnlockPrivate.CredentialProblem.TOO_SHORT); + } + + if (!!credential && this.credentialRequirements.maxLength != 0 && + credential.length > this.credentialRequirements.maxLength) { + errors.push(chrome.quickUnlockPrivate.CredentialProblem.TOO_LONG); + } + + if (!!credential && TEST_WEAK_PINS.includes(credential)) + warnings.push(chrome.quickUnlockPrivate.CredentialProblem.TOO_WEAK); + + message.errors = errors; + message.warnings = warnings; + onComplete(message); + }, + + /** + * @override. + * @param {!chrome.quickUnlockPrivate.QuickUnlockMode} mode + * @param {function( + * !chrome.quickUnlockPrivate.CredentialRequirements):void onComplete + */ + getCredentialRequirements: function(mode, onComplete) { + onComplete(this.credentialRequirements); + }, }; /** @type {!ChromeEvent} */
diff --git a/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js b/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js index 67d62ec..aad0d078 100644 --- a/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js +++ b/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js
@@ -337,6 +337,7 @@ // Create setup-pin element. element = document.createElement('settings-setup-pin-dialog'); + element.quickUnlockPrivate_ = quickUnlockPrivateApi; element.setModes = quickUnlockPrivateApi.setModes.bind(quickUnlockPrivateApi, ''); element.writeUma_ = fakeUma.recordProgress.bind(fakeUma); @@ -402,13 +403,30 @@ pinKeyboard.value = '11'; assertTrue(isVisible(problemDiv)); - assertHasClass(problemDiv, 'warning'); + assertHasClass(problemDiv, 'error'); + assertTrue(continueButton.disabled); + }); + + // If the PIN is too long an error problem is shown. + test('WarningShownForLongPins', function() { + // By default, there is no max length on pins. + quickUnlockPrivateApi.credentialRequirements.maxLength = 5; + + // A pin of length five should be valid when max length is five. + pinKeyboard.value = '11111'; + assertFalse(isVisible(problemDiv)); + assertFalse(continueButton.disabled); + + // A pin of length six should not be valid when max length is five. + pinKeyboard.value = '111111'; + assertTrue(isVisible(problemDiv)); + assertHasClass(problemDiv, 'error'); assertTrue(continueButton.disabled); }); // If the PIN is weak a warning problem is shown. test('WarningShownForWeakPins', function() { - pinKeyboard.value = '111111'; + pinKeyboard.value = '1111'; assertTrue(isVisible(problemDiv)); assertHasClass(problemDiv, 'warning'); @@ -425,8 +443,9 @@ assertTrue(isVisible(problemDiv)); assertHasClass(problemDiv, 'warning'); - // Submitting a mistmatched PIN shows an error. - MockInteractions.tap(continueButton); + // Submitting a mistmatched PIN shows an error. Directly call the button + // event since a tap on the disabled button does nothing. + element.onPinSubmit_(); assertHasClass(problemDiv, 'error'); // Changing the PIN changes the error to a warning.
diff --git a/components/exo/buffer.cc b/components/exo/buffer.cc index 9b1778d..060c7e5 100644 --- a/components/exo/buffer.cc +++ b/components/exo/buffer.cc
@@ -24,6 +24,7 @@ #include "cc/output/context_provider.h" #include "cc/resources/single_release_callback.h" #include "cc/resources/texture_mailbox.h" +#include "components/exo/compositor_frame_sink_holder.h" #include "gpu/command_buffer/client/context_support.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "ui/aura/env.h" @@ -398,10 +399,12 @@ Buffer::~Buffer() {} -std::unique_ptr<cc::SingleReleaseCallback> Buffer::ProduceTextureMailbox( - cc::TextureMailbox* texture_mailbox, +bool Buffer::ProduceTransferableResource( + CompositorFrameSinkHolder* compositor_frame_sink_holder, + cc::ResourceId resource_id, bool secure_output_only, - bool client_usage) { + bool client_usage, + cc::TransferableResource* resource) { DCHECK(attach_count_); DLOG_IF(WARNING, use_count_ && client_usage) << "Producing a texture mailbox for a buffer that has not been released"; @@ -433,9 +436,20 @@ if (!context_provider) { DLOG(WARNING) << "Failed to acquire a context provider"; Release(); // Decrements the use count - return nullptr; + resource->id = 0; + resource->size = gfx::Size(); + return false; } + // The reference to the CompositorFrameSinkHolder keeps it alive until a + // release callback is received. + compositor_frame_sink_holder_ = compositor_frame_sink_holder; + + resource->id = resource_id; + resource->format = cc::RGBA_8888; + resource->filter = GL_LINEAR; + resource->size = gpu_memory_buffer_->GetSize(); + // Create a new image texture for |gpu_memory_buffer_| with |texture_target_| // if one doesn't already exist. The contents of this buffer are copied to // |texture| using a call to CopyTexImage. @@ -450,18 +464,19 @@ Texture* texture = contents_texture_.get(); // This binds the latest contents of this buffer to |texture|. - gpu::SyncToken sync_token = texture->BindTexImage(); + resource->mailbox_holder = gpu::MailboxHolder( + texture->mailbox(), texture->BindTexImage(), texture_target_); - *texture_mailbox = - cc::TextureMailbox(texture->mailbox(), sync_token, texture_target_, - gpu_memory_buffer_->GetSize(), is_overlay_candidate_, - secure_output_only); + resource->is_overlay_candidate = is_overlay_candidate_; + // The contents texture will be released when no longer used by the // compositor. - return cc::SingleReleaseCallback::Create( + compositor_frame_sink_holder_->SetResourceReleaseCallback( + resource_id, base::Bind(&Buffer::Texture::ReleaseTexImage, base::Unretained(texture), base::Bind(&Buffer::ReleaseContentsTexture, AsWeakPtr(), base::Passed(&contents_texture_)))); + return true; } // Create a mailbox texture that we copy the buffer contents to. @@ -476,19 +491,22 @@ Texture* texture = texture_.get(); // The contents texture will be released when copy has completed. - gpu::SyncToken sync_token = contents_texture->CopyTexImage( - texture, base::Bind(&Buffer::ReleaseContentsTexture, AsWeakPtr(), - base::Passed(&contents_texture_))); - *texture_mailbox = - cc::TextureMailbox(texture->mailbox(), sync_token, GL_TEXTURE_2D, - gpu_memory_buffer_->GetSize(), - false /* is_overlay_candidate */, secure_output_only); + resource->mailbox_holder = gpu::MailboxHolder( + texture->mailbox(), + contents_texture->CopyTexImage( + texture, base::Bind(&Buffer::ReleaseContentsTexture, AsWeakPtr(), + base::Passed(&contents_texture_))), + GL_TEXTURE_2D); + resource->is_overlay_candidate = false; + // The mailbox texture will be released when no longer used by the // compositor. - return cc::SingleReleaseCallback::Create( + compositor_frame_sink_holder_->SetResourceReleaseCallback( + resource_id, base::Bind(&Buffer::Texture::Release, base::Unretained(texture), base::Bind(&Buffer::ReleaseTexture, AsWeakPtr(), base::Passed(&texture_)))); + return true; } void Buffer::OnAttach() { @@ -534,6 +552,8 @@ // Run release callback to notify the client that buffer has been released. if (!release_callback_.is_null()) release_callback_.Run(); + + compositor_frame_sink_holder_ = nullptr; } void Buffer::ReleaseTexture(std::unique_ptr<Texture> texture) { @@ -542,7 +562,6 @@ void Buffer::ReleaseContentsTexture(std::unique_ptr<Texture> texture) { TRACE_EVENT0("exo", "Buffer::ReleaseContentsTexture"); - contents_texture_ = std::move(texture); Release(); }
diff --git a/components/exo/buffer.h b/components/exo/buffer.h index e7b5b605..eeaf1c3 100644 --- a/components/exo/buffer.h +++ b/components/exo/buffer.h
@@ -10,6 +10,7 @@ #include "base/callback.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "cc/resources/transferable_resource.h" #include "ui/gfx/geometry/size.h" namespace base { @@ -18,17 +19,14 @@ } } -namespace cc { -class SingleReleaseCallback; -class TextureMailbox; -} - namespace gfx { class GpuMemoryBuffer; } namespace exo { +class CompositorFrameSinkHolder; + // This class provides the content for a Surface. The mechanism by which a // client provides and updates the contents is the responsibility of the client // and not defined as part of this class. @@ -53,10 +51,12 @@ // buffer. Returns a release callback on success. The release callback should // be called before a new texture mailbox can be acquired unless // |non_client_usage| is true. - std::unique_ptr<cc::SingleReleaseCallback> ProduceTextureMailbox( - cc::TextureMailbox* mailbox, + bool ProduceTransferableResource( + CompositorFrameSinkHolder* compositor_frame_sink_holder, + cc::ResourceId resource_id, bool secure_output_only, - bool client_usage); + bool client_usage, + cc::TransferableResource* resource); // This should be called when the buffer is attached to a Surface. void OnAttach(); @@ -123,6 +123,12 @@ // The client release callback. base::Closure release_callback_; + // The CompositorFrameSinkHolder that has the ReleaseCallback of this buffer + // produced in ProduceTextureMailbox(). + // Buffer holds a reference to the CompositorFrameSinkHolder to keep it alive. + // The refptr is reset when the release callback is called. + scoped_refptr<CompositorFrameSinkHolder> compositor_frame_sink_holder_; + DISALLOW_COPY_AND_ASSIGN(Buffer); };
diff --git a/components/exo/buffer_unittest.cc b/components/exo/buffer_unittest.cc index 987c2905..8572caa 100644 --- a/components/exo/buffer_unittest.cc +++ b/components/exo/buffer_unittest.cc
@@ -31,6 +31,9 @@ gfx::Size buffer_size(256, 256); std::unique_ptr<Buffer> buffer( new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + std::unique_ptr<Surface> surface(new Surface); + scoped_refptr<CompositorFrameSinkHolder> compositor_frame_sink_holder = + new CompositorFrameSinkHolder(surface.get(), nullptr, nullptr); // Set the release callback. int release_call_count = 0; @@ -38,15 +41,21 @@ base::Bind(&Release, base::Unretained(&release_call_count))); buffer->OnAttach(); - // Produce a texture mailbox for the contents of the buffer. - cc::TextureMailbox texture_mailbox; - std::unique_ptr<cc::SingleReleaseCallback> buffer_release_callback = - buffer->ProduceTextureMailbox(&texture_mailbox, false, true); - ASSERT_TRUE(buffer_release_callback); + cc::TransferableResource resource; + // Produce a transferable resource for the contents of the buffer. + bool rv = buffer->ProduceTransferableResource( + compositor_frame_sink_holder.get(), 0, false, true, &resource); + ASSERT_TRUE(rv); // Release buffer. - buffer_release_callback->Run(gpu::SyncToken(), false); + cc::ReturnedResource returned_resource; + returned_resource.id = resource.id; + returned_resource.sync_token = resource.mailbox_holder.sync_token; + returned_resource.lost = false; + cc::ReturnedResourceArray resources = {returned_resource}; + compositor_frame_sink_holder->ReclaimResources(resources); + RunAllPendingInMessageLoop(); ASSERT_EQ(release_call_count, 0); buffer->OnDetach(); @@ -59,13 +68,17 @@ gfx::Size buffer_size(256, 256); std::unique_ptr<Buffer> buffer( new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + std::unique_ptr<Surface> surface(new Surface); + scoped_refptr<CompositorFrameSinkHolder> compositor_frame_sink_holder = + new CompositorFrameSinkHolder(surface.get(), nullptr, nullptr); + cc::ResourceId resource_id = 0; buffer->OnAttach(); - // Acquire a texture mailbox for the contents of the buffer. - cc::TextureMailbox texture_mailbox; - std::unique_ptr<cc::SingleReleaseCallback> buffer_release_callback = - buffer->ProduceTextureMailbox(&texture_mailbox, false, true); - ASSERT_TRUE(buffer_release_callback); + // Acquire a texture transferable resource for the contents of the buffer. + cc::TransferableResource resource; + bool rv = buffer->ProduceTransferableResource( + compositor_frame_sink_holder.get(), resource_id, false, true, &resource); + ASSERT_TRUE(rv); scoped_refptr<cc::ContextProvider> context_provider = aura::Env::GetInstance() @@ -79,15 +92,31 @@ // Release buffer. bool is_lost = true; - buffer_release_callback->Run(gpu::SyncToken(), is_lost); + cc::ReturnedResource returned_resource; + returned_resource.id = resource_id; + returned_resource.sync_token = gpu::SyncToken(); + returned_resource.lost = is_lost; + cc::ReturnedResourceArray resources = {returned_resource}; + compositor_frame_sink_holder->ReclaimResources(resources); + RunAllPendingInMessageLoop(); - // Producing a new texture mailbox for the contents of the buffer. - std::unique_ptr<cc::SingleReleaseCallback> buffer_release_callback2 = - buffer->ProduceTextureMailbox(&texture_mailbox, false, false); - ASSERT_TRUE(buffer_release_callback2); + // Producing a new texture transferable resource for the contents of the + // buffer. + ++resource_id; + cc::TransferableResource new_resource; + rv = buffer->ProduceTransferableResource(compositor_frame_sink_holder.get(), + resource_id, false, false, + &new_resource); + ASSERT_TRUE(rv); buffer->OnDetach(); - buffer_release_callback2->Run(gpu::SyncToken(), false); + cc::ReturnedResource returned_resource2; + returned_resource2.id = resource_id; + returned_resource2.sync_token = gpu::SyncToken(); + returned_resource2.lost = false; + cc::ReturnedResourceArray resources2 = {returned_resource2}; + compositor_frame_sink_holder->ReclaimResources(resources2); + RunAllPendingInMessageLoop(); } } // namespace
diff --git a/components/exo/compositor_frame_sink_holder.cc b/components/exo/compositor_frame_sink_holder.cc index dcd3110a..e6cb2b8d 100644 --- a/components/exo/compositor_frame_sink_holder.cc +++ b/components/exo/compositor_frame_sink_holder.cc
@@ -4,7 +4,6 @@ #include "components/exo/compositor_frame_sink_holder.h" -#include "base/memory/ptr_util.h" #include "cc/resources/returned_resource.h" #include "components/exo/surface.h" @@ -30,10 +29,11 @@ return release_callbacks_.find(id) != release_callbacks_.end(); } -void CompositorFrameSinkHolder::AddResourceReleaseCallback( +void CompositorFrameSinkHolder::SetResourceReleaseCallback( cc::ResourceId id, - std::unique_ptr<cc::SingleReleaseCallback> callback) { - release_callbacks_[id] = std::make_pair(this, std::move(callback)); + const cc::ReleaseCallback& callback) { + DCHECK(!callback.is_null()); + release_callbacks_[id] = callback; } void CompositorFrameSinkHolder::ActivateFrameCallbacks( @@ -84,10 +84,10 @@ for (auto& resource : resources) { auto it = release_callbacks_.find(resource.id); DCHECK(it != release_callbacks_.end()); - std::unique_ptr<cc::SingleReleaseCallback> callback = - std::move(it->second.second); - release_callbacks_.erase(it); - callback->Run(resource.sync_token, resource.lost); + if (it != release_callbacks_.end()) { + it->second.Run(resource.sync_token, resource.lost); + release_callbacks_.erase(it); + } } } @@ -126,7 +126,10 @@ //////////////////////////////////////////////////////////////////////////////// // ExoComopositorFrameSink, private: -CompositorFrameSinkHolder::~CompositorFrameSinkHolder() {} +CompositorFrameSinkHolder::~CompositorFrameSinkHolder() { + if (surface_) + surface_->RemoveSurfaceObserver(this); +} void CompositorFrameSinkHolder::UpdateNeedsBeginFrame() { if (!begin_frame_source_)
diff --git a/components/exo/compositor_frame_sink_holder.h b/components/exo/compositor_frame_sink_holder.h index 59cc987..d2f8ab8f 100644 --- a/components/exo/compositor_frame_sink_holder.h +++ b/components/exo/compositor_frame_sink_holder.h
@@ -10,7 +10,7 @@ #include <memory> #include "cc/ipc/mojo_compositor_frame_sink.mojom.h" -#include "cc/resources/single_release_callback.h" +#include "cc/resources/release_callback.h" #include "cc/resources/transferable_resource.h" #include "cc/scheduler/begin_frame_source.h" #include "components/exo/compositor_frame_sink.h" @@ -37,9 +37,8 @@ cc::mojom::MojoCompositorFrameSinkClientRequest request); bool HasReleaseCallbackForResource(cc::ResourceId id); - void AddResourceReleaseCallback( - cc::ResourceId id, - std::unique_ptr<cc::SingleReleaseCallback> callback); + void SetResourceReleaseCallback(cc::ResourceId id, + const cc::ReleaseCallback& callback); CompositorFrameSink* GetCompositorFrameSink() { return frame_sink_.get(); } @@ -79,14 +78,8 @@ void UpdateNeedsBeginFrame(); - // Each release callback holds a reference to the CompositorFrameSinkHolder - // itself to keep it alive. Running and erasing the callbacks might result in - // the instance being destroyed. Therefore, we should not access any member - // variables after running and erasing the callbacks. - using ResourceReleaseCallbackMap = - std::map<int, - std::pair<scoped_refptr<CompositorFrameSinkHolder>, - std::unique_ptr<cc::SingleReleaseCallback>>>; + // A collection of callbacks used to release resources. + using ResourceReleaseCallbackMap = std::map<int, cc::ReleaseCallback>; ResourceReleaseCallbackMap release_callbacks_; Surface* surface_;
diff --git a/components/exo/surface.cc b/components/exo/surface.cc index 6c81151..e2f8d4a 100644 --- a/components/exo/surface.cc +++ b/components/exo/surface.cc
@@ -658,32 +658,11 @@ } void Surface::UpdateResource(bool client_usage) { - std::unique_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback; - - cc::TextureMailbox texture_mailbox; - if (current_buffer_.buffer()) { - texture_mailbox_release_callback = - current_buffer_.buffer()->ProduceTextureMailbox( - &texture_mailbox, state_.only_visible_on_secure_output, - client_usage); - } - - if (texture_mailbox_release_callback) { - cc::TransferableResource resource; - resource.id = next_resource_id_++; - resource.format = cc::RGBA_8888; - resource.filter = - texture_mailbox.nearest_neighbor() ? GL_NEAREST : GL_LINEAR; - resource.size = texture_mailbox.size_in_pixels(); - resource.mailbox_holder = gpu::MailboxHolder(texture_mailbox.mailbox(), - texture_mailbox.sync_token(), - texture_mailbox.target()); - resource.is_overlay_candidate = texture_mailbox.is_overlay_candidate(); - - compositor_frame_sink_holder_->AddResourceReleaseCallback( - resource.id, std::move(texture_mailbox_release_callback)); - current_resource_ = resource; - } else { + if (!current_buffer_.buffer() || + !current_buffer_.buffer()->ProduceTransferableResource( + compositor_frame_sink_holder_.get(), next_resource_id_++, + state_.only_visible_on_secure_output, client_usage, + ¤t_resource_)) { current_resource_.id = 0; current_resource_.size = gfx::Size(); }
diff --git a/components/offline_pages/core/offline_page_model_impl.cc b/components/offline_pages/core/offline_page_model_impl.cc index 011dfbe..245db22 100644 --- a/components/offline_pages/core/offline_page_model_impl.cc +++ b/components/offline_pages/core/offline_page_model_impl.cc
@@ -708,11 +708,12 @@ store_->AddOfflinePage(offline_page_item, base::Bind(&OfflinePageModelImpl::OnAddOfflinePageDone, weak_ptr_factory_.GetWeakPtr(), archiver, - callback, offline_page_item)); + file_path, callback, offline_page_item)); } void OfflinePageModelImpl::OnAddOfflinePageDone( OfflinePageArchiver* archiver, + const base::FilePath& file_path, const SavePageCallback& callback, const OfflinePageItem& offline_page, ItemActionStatus status) { @@ -727,6 +728,8 @@ offline_page.client_id.name_space, offline_page.url.spec(), std::to_string(offline_page.offline_id)); } else if (status == ItemActionStatus::ALREADY_EXISTS) { + // Remove the orphaned archive. No callback necessary. + archive_manager_->DeleteArchive(file_path, base::Bind([](bool) {})); result = SavePageResult::ALREADY_EXISTS; } else { result = SavePageResult::STORE_FAILURE;
diff --git a/components/offline_pages/core/offline_page_model_impl.h b/components/offline_pages/core/offline_page_model_impl.h index 15846d5..d0ca9bb5 100644 --- a/components/offline_pages/core/offline_page_model_impl.h +++ b/components/offline_pages/core/offline_page_model_impl.h
@@ -169,6 +169,7 @@ const base::string16& title, int64_t file_size); void OnAddOfflinePageDone(OfflinePageArchiver* archiver, + const base::FilePath& file_path, const SavePageCallback& callback, const OfflinePageItem& offline_page, ItemActionStatus status);
diff --git a/components/sync/syncable/model_type.cc b/components/sync/syncable/model_type.cc index a4d34f1..363c848 100644 --- a/components/sync/syncable/model_type.cc +++ b/components/sync/syncable/model_type.cc
@@ -31,23 +31,23 @@ namespace syncer { struct ModelTypeInfo { - const ModelType model_type; + ModelType model_type; // Model Type notification string. // This needs to match the corresponding proto message name in sync.proto - const char* const notification_type; + const char* notification_type; // Root tag for Model Type // This should be the same as the model type but all lowercase. - const char* const root_tag; + const char* root_tag; // String value for Model Type // This should be the same as the model type but space separated and the // first letter of every word capitalized. - const char* const model_type_string; + const char* model_type_string; // SpecificsFieldNumber for Model Type - const int specifics_field_number; + int specifics_field_number; // Histogram value should be unique for the Model Type, Existing histogram // values should never be modified without updating "SyncModelTypes" enum in // histograms.xml to maintain backward compatibility. - const int model_type_histogram_val; + int model_type_histogram_val; }; // Below struct entries are in the same order as their definition in the
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 4d681cc1..9c7cd17cb0 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -1141,6 +1141,8 @@ "renderer_host/media/video_capture_host.h", "renderer_host/media/video_capture_manager.cc", "renderer_host/media/video_capture_manager.h", + "renderer_host/media/video_frame_receiver_on_io_thread.cc", + "renderer_host/media/video_frame_receiver_on_io_thread.h", "renderer_host/native_web_keyboard_event_aura.cc", "renderer_host/native_web_keyboard_event_mac.mm", "renderer_host/offscreen_canvas_compositor_frame_sink.cc",
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.cc b/content/browser/accessibility/browser_accessibility_manager_android.cc index 440767b0..3f7121b5 100644 --- a/content/browser/accessibility/browser_accessibility_manager_android.cc +++ b/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -920,11 +920,6 @@ return; node->manager()->SetAccessibilityFocus(*node); - - // Auto-focus links, because some websites have skip links that are - // only visible when focused. See http://crbug.com/657157 - if (node->IsLink()) - node->manager()->SetFocus(*node); } bool BrowserAccessibilityManagerAndroid::IsSlider(
diff --git a/content/browser/loader/redirect_to_file_resource_handler.cc b/content/browser/loader/redirect_to_file_resource_handler.cc index 2d55420e..a30d9dc 100644 --- a/content/browser/loader/redirect_to_file_resource_handler.cc +++ b/content/browser/loader/redirect_to_file_resource_handler.cc
@@ -172,6 +172,7 @@ // network request like this. will_start_url_ = url; did_defer_ = *defer = true; + request()->LogBlockedBy("RedirectToFileResourceHandler"); if (create_temporary_file_stream_.is_null()) { CreateTemporaryFileStream( base::Bind(&RedirectToFileResourceHandler::DidCreateTemporaryFile, @@ -215,6 +216,7 @@ if (BufIsFull()) { did_defer_ = *defer = true; + request()->LogBlockedBy("RedirectToFileResourceHandler"); if (buf_->capacity() == bytes_read) { // The network layer has saturated our buffer in one read. Next time, we @@ -234,6 +236,7 @@ completed_status_ = status; did_defer_ = true; *defer = true; + request()->LogBlockedBy("RedirectToFileResourceHandler"); return; } next_handler_->OnResponseCompleted(status, defer); @@ -254,10 +257,11 @@ // Resume the request. DCHECK(did_defer_); bool defer = false; + request()->LogUnblocked(); if (!next_handler_->OnWillStart(will_start_url_, &defer)) { controller()->Cancel(); } else if (!defer) { - ResumeIfDeferred(); + Resume(); } else { did_defer_ = false; } @@ -293,9 +297,10 @@ // this should run even in the |failed| case above, otherwise a failed write // leaves the handler stuck. bool defer = false; + request()->LogUnblocked(); next_handler_->OnResponseCompleted(completed_status_, &defer); if (!defer) { - ResumeIfDeferred(); + Resume(); } else { did_defer_ = false; } @@ -309,8 +314,10 @@ // We've caught up to the network load, but it may be in the process of // appending more data to the buffer. if (!buf_write_pending_) { - if (BufIsFull()) - ResumeIfDeferred(); + if (BufIsFull()) { + request()->LogUnblocked(); + Resume(); + } buf_->set_offset(0); write_cursor_ = 0; } @@ -356,11 +363,10 @@ return buf_->RemainingCapacity() <= (2 * net::kMaxBytesToSniff); } -void RedirectToFileResourceHandler::ResumeIfDeferred() { - if (did_defer_) { - did_defer_ = false; - controller()->Resume(); - } +void RedirectToFileResourceHandler::Resume() { + DCHECK(did_defer_); + did_defer_ = false; + controller()->Resume(); } } // namespace content
diff --git a/content/browser/loader/redirect_to_file_resource_handler.h b/content/browser/loader/redirect_to_file_resource_handler.h index bcda474..8163a42 100644 --- a/content/browser/loader/redirect_to_file_resource_handler.h +++ b/content/browser/loader/redirect_to_file_resource_handler.h
@@ -76,7 +76,7 @@ bool WriteMore(); bool BufIsFull() const; - void ResumeIfDeferred(); + void Resume(); CreateTemporaryFileStreamFunction create_temporary_file_stream_;
diff --git a/content/browser/loader/resource_scheduler.cc b/content/browser/loader/resource_scheduler.cc index 9bbae929..1cd91c3e 100644 --- a/content/browser/loader/resource_scheduler.cc +++ b/content/browser/loader/resource_scheduler.cc
@@ -52,6 +52,38 @@ const RequestAttributes kAttributeDelayable = 0x02; const RequestAttributes kAttributeLayoutBlocking = 0x04; +// Reasons why pending requests may be started. For logging only. +enum class RequestStartTrigger { + NONE, + COMPLETION_PRE_BODY, + COMPLETION_POST_BODY, + BODY_REACHED, + CLIENT_KILL, + SPDY_PROXY_DETECTED, + REQUEST_REPRIORITIZED, +}; + +const char* RequestStartTriggerString(RequestStartTrigger trigger) { + switch (trigger) { + case RequestStartTrigger::NONE: + return "NONE"; + case RequestStartTrigger::COMPLETION_PRE_BODY: + return "COMPLETION_PRE_BODY"; + case RequestStartTrigger::COMPLETION_POST_BODY: + return "COMPLETION_POST_BODY"; + case RequestStartTrigger::BODY_REACHED: + return "BODY_REACHED"; + case RequestStartTrigger::CLIENT_KILL: + return "CLIENT_KILL"; + case RequestStartTrigger::SPDY_PROXY_DETECTED: + return "SPDY_PROXY_DETECTED"; + case RequestStartTrigger::REQUEST_REPRIORITIZED: + return "REQUEST_REPRIORITIZED"; + } + NOTREACHED(); + return "Unknown"; +} + } // namespace // The maximum number of delayable requests to allow to be in-flight at any @@ -331,7 +363,7 @@ SetRequestAttributes(request, DetermineRequestAttributes(request)); if (ShouldStartRequest(request) == START_REQUEST) { // New requests can be started synchronously without issue. - StartRequest(request, START_SYNC); + StartRequest(request, START_SYNC, RequestStartTrigger::NONE); } else { pending_requests_.Insert(request); } @@ -345,7 +377,10 @@ EraseInFlightRequest(request); // Removing this request may have freed up another to load. - LoadAnyStartablePendingRequests(); + LoadAnyStartablePendingRequests( + has_html_body_ + ? RequestStartTrigger::COMPLETION_POST_BODY + : RequestStartTrigger::COMPLETION_PRE_BODY); } } @@ -362,7 +397,7 @@ pending_requests_.Erase(request); // Starting requests asynchronously ensures no side effects, and avoids // starting a bunch of requests that may be about to be deleted. - StartRequest(request, START_ASYNC); + StartRequest(request, START_ASYNC, RequestStartTrigger::CLIENT_KILL); } RequestSet unowned_requests; for (RequestSet::iterator it = in_flight_requests_.begin(); @@ -387,13 +422,13 @@ void OnWillInsertBody() { has_html_body_ = true; - LoadAnyStartablePendingRequests(); + LoadAnyStartablePendingRequests(RequestStartTrigger::BODY_REACHED); } void OnReceivedSpdyProxiedHttpResponse() { if (!using_spdy_proxy_) { using_spdy_proxy_ = true; - LoadAnyStartablePendingRequests(); + LoadAnyStartablePendingRequests(RequestStartTrigger::SPDY_PROXY_DETECTED); } } @@ -414,7 +449,8 @@ if (new_priority_params.priority > old_priority_params.priority) { // Check if this request is now able to load at its new priority. - LoadAnyStartablePendingRequests(); + LoadAnyStartablePendingRequests( + RequestStartTrigger::REQUEST_REPRIORITIZED); } } @@ -560,7 +596,16 @@ } void StartRequest(ScheduledResourceRequest* request, - StartMode start_mode) { + StartMode start_mode, + RequestStartTrigger trigger) { + // Only log on requests that were blocked by the ResourceScheduler. + if (start_mode == START_ASYNC) { + DCHECK_NE(RequestStartTrigger::NONE, trigger); + request->url_request()->net_log().AddEvent( + net::NetLogEventType::RESOURCE_SCHEDULER_REQUEST_STARTED, + net::NetLog::StringCallback( + "trigger", RequestStartTriggerString(trigger))); + } InsertInFlightRequest(request); request->Start(start_mode); } @@ -670,7 +715,7 @@ return START_REQUEST; } - void LoadAnyStartablePendingRequests() { + void LoadAnyStartablePendingRequests(RequestStartTrigger trigger) { // We iterate through all the pending requests, starting with the highest // priority one. For each entry, one of three things can happen: // 1) We start the request, remove it from the list, and keep checking. @@ -688,7 +733,7 @@ if (query_result == START_REQUEST) { pending_requests_.Erase(request); - StartRequest(request, START_ASYNC); + StartRequest(request, START_ASYNC, trigger); // StartRequest can modify the pending list, so we (re)start evaluation // from the currently highest priority request. Avoid copying a singular
diff --git a/content/browser/media/capture/web_contents_tracker.cc b/content/browser/media/capture/web_contents_tracker.cc index 668eb6d..770cb1e 100644 --- a/content/browser/media/capture/web_contents_tracker.cc +++ b/content/browser/media/capture/web_contents_tracker.cc
@@ -5,21 +5,20 @@ #include "content/browser/media/capture/web_contents_tracker.h" #include "base/threading/thread_task_runner_handle.h" -#include "content/browser/frame_host/render_frame_host_impl.h" -#include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents.h" namespace content { -WebContentsTracker::WebContentsTracker(bool track_fullscreen_rwh) - : track_fullscreen_rwh_(track_fullscreen_rwh), - last_target_(NULL) {} +WebContentsTracker::WebContentsTracker(bool track_fullscreen_rwhv) + : track_fullscreen_rwhv_(track_fullscreen_rwhv), + last_target_view_(nullptr) {} WebContentsTracker::~WebContentsTracker() { - DCHECK(!web_contents()) << "BUG: Still observering!"; + // Likely unintentional BUG if Stop() was not called before this point. + DCHECK(!web_contents()); } void WebContentsTracker::Start(int render_process_id, int main_render_frame_id, @@ -47,36 +46,34 @@ resize_callback_.Reset(); if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { - WebContentsObserver::Observe(NULL); + WebContentsObserver::Observe(nullptr); } else { - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&WebContentsTracker::Observe, this, - static_cast<WebContents*>(NULL))); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&WebContentsTracker::Observe, this, + static_cast<WebContents*>(nullptr))); } } -RenderWidgetHost* WebContentsTracker::GetTargetRenderWidgetHost() const { +RenderWidgetHostView* WebContentsTracker::GetTargetView() const { DCHECK_CURRENTLY_ON(BrowserThread::UI); WebContents* const wc = web_contents(); if (!wc) - return NULL; + return nullptr; - RenderWidgetHost* rwh = NULL; - if (track_fullscreen_rwh_) { - RenderWidgetHostView* const view = wc->GetFullscreenRenderWidgetHostView(); - if (view) - rwh = view->GetRenderWidgetHost(); - } - if (!rwh) { - RenderFrameHostImpl* const rfh = - static_cast<RenderFrameHostImpl*>(wc->GetMainFrame()); - if (rfh) - rwh = rfh->GetRenderWidgetHost(); + if (track_fullscreen_rwhv_) { + if (auto* view = wc->GetFullscreenRenderWidgetHostView()) + return view; } - return rwh; + if (auto* view = wc->GetRenderWidgetHostView()) { + // Make sure the RWHV is still associated with a RWH before considering the + // view "alive." This is because a null RWH indicates the RWHV has had its + // Destroy() method called. + if (view->GetRenderWidgetHost()) + return view; + } + return nullptr; } void WebContentsTracker::SetResizeChangeCallback( @@ -88,21 +85,23 @@ void WebContentsTracker::OnPossibleTargetChange(bool force_callback_run) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - RenderWidgetHost* const rwh = GetTargetRenderWidgetHost(); - if (rwh == last_target_ && !force_callback_run) + RenderWidgetHostView* const rwhv = GetTargetView(); + if (rwhv == last_target_view_ && !force_callback_run) { + DVLOG(1) << "No target view change (RenderWidgetHostView@" << rwhv << ')'; return; - DVLOG(1) << "Will report target change from RenderWidgetHost@" << last_target_ - << " to RenderWidgetHost@" << rwh; - last_target_ = rwh; + } + DVLOG(1) << "Will report target change from RenderWidgetHostView@" + << last_target_view_ << " to RenderWidgetHostView@" << rwhv; + last_target_view_ = rwhv; if (task_runner_->BelongsToCurrentThread()) { - MaybeDoCallback(rwh != nullptr); + MaybeDoCallback(is_still_tracking()); return; } - task_runner_->PostTask( - FROM_HERE, - base::Bind(&WebContentsTracker::MaybeDoCallback, this, rwh != nullptr)); + task_runner_->PostTask(FROM_HERE, + base::Bind(&WebContentsTracker::MaybeDoCallback, this, + is_still_tracking())); } void WebContentsTracker::MaybeDoCallback(bool was_still_tracking) { @@ -135,13 +134,22 @@ OnPossibleTargetChange(true); } +void WebContentsTracker::RenderFrameCreated( + RenderFrameHost* render_frame_host) { + DVLOG(1) << "RenderFrameCreated(rfh=" << render_frame_host << ')'; + OnPossibleTargetChange(false); +} + void WebContentsTracker::RenderFrameDeleted( RenderFrameHost* render_frame_host) { + DVLOG(1) << "RenderFrameDeleted(rfh=" << render_frame_host << ')'; OnPossibleTargetChange(false); } void WebContentsTracker::RenderFrameHostChanged(RenderFrameHost* old_host, RenderFrameHost* new_host) { + DVLOG(1) << "RenderFrameHostChanged(old=" << old_host << ", new=" << new_host + << ')'; OnPossibleTargetChange(false); } @@ -159,15 +167,18 @@ } void WebContentsTracker::WebContentsDestroyed() { - Observe(NULL); - OnPossibleTargetChange(false); + DVLOG(1) << "WebContentsDestroyed()"; + Observe(nullptr); + OnPossibleTargetChange(true); } void WebContentsTracker::DidShowFullscreenWidget() { + DVLOG(1) << "DidShowFullscreenWidget()"; OnPossibleTargetChange(false); } void WebContentsTracker::DidDestroyFullscreenWidget() { + DVLOG(1) << "DidDestroyFullscreenWidget()"; OnPossibleTargetChange(false); }
diff --git a/content/browser/media/capture/web_contents_tracker.h b/content/browser/media/capture/web_contents_tracker.h index aacbfcf..0805772 100644 --- a/content/browser/media/capture/web_contents_tracker.h +++ b/content/browser/media/capture/web_contents_tracker.h
@@ -4,14 +4,13 @@ // // Given a starting render_process_id and main_render_frame_id, the // WebContentsTracker tracks changes to the active RenderFrameHost tree during -// the lifetime of a WebContents instance. This is used when mirroring tab -// video and audio so that user navigations, crashes, iframes, etc., during a -// tab's lifetime allow the capturing code to remain active on the -// current/latest render frame tree. +// the lifetime of a WebContents instance. This is used to maintain capture of +// the WebContents's video and audio across page transitions such as user +// navigations, crashes, iframes, etc.. // -// Threading issues: Start(), Stop() and the ChangeCallback are invoked on the -// same thread. This can be any thread, and the decision is locked-in by -// WebContentsTracker when Start() is called. +// Threading issues: Start(), Stop() and the ChangeCallback must be invoked on +// the same thread. This can be any thread, and the decision is locked-in once +// WebContentsTracker::Start() is called. #ifndef CONTENT_BROWSER_MEDIA_CAPTURE_WEB_CONTENTS_TRACKER_H_ #define CONTENT_BROWSER_MEDIA_CAPTURE_WEB_CONTENTS_TRACKER_H_ @@ -28,21 +27,22 @@ namespace content { -class RenderWidgetHost; +class RenderWidgetHostView; class CONTENT_EXPORT WebContentsTracker : public base::RefCountedThreadSafe<WebContentsTracker>, public WebContentsObserver { public: - // If |track_fullscreen_rwh| is true, the ChangeCallback will be run when a - // WebContents shows/destroys a fullscreen RenderWidgetHost view. If false, - // fullscreen events are ignored. Specify true for video tab capture and - // false for audio tab capture. - explicit WebContentsTracker(bool track_fullscreen_rwh); + // If |track_fullscreen_rwhv| is true, the ChangeCallback will be run when a + // WebContents shows/destroys a fullscreen RenderWidgetHostView. If false, + // fullscreen events are ignored. Normally, specify true for video capture and + // false for audio capture. + explicit WebContentsTracker(bool track_fullscreen_rwhv); - // Callback to indicate a new RenderWidgetHost should be targeted for capture. - // This is also invoked with false to indicate tracking will not continue - // (i.e., the WebContents instance was not found or has been destroyed). + // Callback to indicate a new RenderWidgetHostView should be targeted for + // capture. This is also invoked with false to indicate tracking will not + // continue (i.e., the WebContents instance was not found or has been + // destroyed). typedef base::Callback<void(bool was_still_tracking)> ChangeCallback; // Start tracking. The last-known |render_process_id| and @@ -57,8 +57,13 @@ // be invoked again. virtual void Stop(); - // Current target. This must only be called on the UI BrowserThread. - RenderWidgetHost* GetTargetRenderWidgetHost() const; + // Returns true if this tracker is still able to continue tracking changes. + // This must only be called on the UI BrowserThread. + bool is_still_tracking() const { return !!web_contents(); } + + // Current target view. May return nullptr during certain transient periods. + // This must only be called on the UI BrowserThread. + RenderWidgetHostView* GetTargetView() const; // Set a callback that is run whenever the main frame of the WebContents is // resized. This method must be called on the same thread that calls @@ -71,10 +76,10 @@ ~WebContentsTracker() override; private: - // Determine the target RenderWidgetHost and, if different from that last - // reported, runs the ChangeCallback on the appropriate thread. If + // Determine the target RenderWidgetHostView and, if different from that last + // reported, runs the ChangeCallback on the appropriate thread. If // |force_callback_run| is true, the ChangeCallback is run even if the - // RenderWidgetHost has not changed. + // RenderWidgetHostView has not changed. void OnPossibleTargetChange(bool force_callback_run); // Called on the thread that Start()/Stop() are called on. Checks whether the @@ -91,41 +96,41 @@ void StartObservingWebContents(int render_process_id, int main_render_frame_id); - // WebContentsObserver overrides: According to web_contents_observer.h, these - // two method overrides are all that is necessary to track the set of active - // RenderFrameHosts. - void RenderFrameDeleted(RenderFrameHost* render_frame_host) override; + // WebContentsObserver overrides: These events indicate that the view of the + // main frame may have changed. + void RenderFrameCreated(RenderFrameHost* render_frame_host) final; + void RenderFrameDeleted(RenderFrameHost* render_frame_host) final; void RenderFrameHostChanged(RenderFrameHost* old_host, - RenderFrameHost* new_host) override; + RenderFrameHost* new_host) final; // WebContentsObserver override to notify the client that the source size has // changed. - void MainFrameWasResized(bool width_changed) override; + void MainFrameWasResized(bool width_changed) final; // WebContentsObserver override to notify the client that the capture target // has been permanently lost. - void WebContentsDestroyed() override; + void WebContentsDestroyed() final; // WebContentsObserver overrides to notify the client that the capture target // may have changed due to a separate fullscreen widget shown/destroyed. - void DidShowFullscreenWidget() override; - void DidDestroyFullscreenWidget() override; + void DidShowFullscreenWidget() final; + void DidDestroyFullscreenWidget() final; // If true, the client is interested in the showing/destruction of fullscreen - // RenderWidgetHosts. - const bool track_fullscreen_rwh_; + // RenderWidgetHostViews. + const bool track_fullscreen_rwhv_; + + // Pointer to the RenderWidgetHostView provided in the last run of + // |callback_|. This is used to eliminate duplicate callback runs. + RenderWidgetHostView* last_target_view_; // TaskRunner corresponding to the thread that called Start(). scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - // Callback to run when the target RenderWidgetHost has changed. + // Callback to run when the target RenderWidgetHostView has changed. ChangeCallback callback_; - // Pointer to the RenderWidgetHost provided in the last run of |callback_|. - // This is used to eliminate duplicate callback runs. - RenderWidgetHost* last_target_; - - // Callback to run when the target RenderWidgetHost has resized. + // Callback to run when the target RenderWidgetHostView has resized. base::Closure resize_callback_; DISALLOW_COPY_AND_ASSIGN(WebContentsTracker);
diff --git a/content/browser/media/capture/web_contents_video_capture_device.cc b/content/browser/media/capture/web_contents_video_capture_device.cc index d258238e..aae4ed1d 100644 --- a/content/browser/media/capture/web_contents_video_capture_device.cc +++ b/content/browser/media/capture/web_contents_video_capture_device.cc
@@ -155,7 +155,7 @@ base::WeakPtrFactory<FrameSubscriber> weak_ptr_factory_; }; -// ContentCaptureSubscription is the relationship between a RenderWidgetHost +// ContentCaptureSubscription is the relationship between a RenderWidgetHostView // whose content is updating, a subscriber that is deciding which of these // updates to capture (and where to deliver them to), and a callback that // knows how to do the capture and prepare the result for delivery. @@ -180,7 +180,7 @@ // subscription will invoke |capture_callback| on the UI thread to do the // work. ContentCaptureSubscription( - const RenderWidgetHost& source, + base::WeakPtr<RenderWidgetHostViewBase> source_view, const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy, const CaptureCallback& capture_callback); ~ContentCaptureSubscription(); @@ -191,11 +191,7 @@ // Called for active frame refresh requests, or mouse activity events. void OnEvent(FrameSubscriber* subscriber); - // Maintain a weak reference to the RenderWidgetHost (via its routing ID), - // since the instance could be destroyed externally during the lifetime of - // |this|. - const int render_process_id_; - const int render_widget_id_; + const base::WeakPtr<RenderWidgetHostViewBase> source_view_; std::unique_ptr<FrameSubscriber> refresh_subscriber_; std::unique_ptr<FrameSubscriber> mouse_activity_subscriber_; @@ -288,9 +284,10 @@ const gfx::Rect& region_in_frame, bool success); - // Remove the old subscription, and attempt to start a new one if |had_target| - // is true. - void RenewFrameSubscription(bool had_target); + // Remove the old subscription, and attempt to start a new one. If + // |is_still_tracking| is false, emit an error rather than attempt to start a + // new subscription. + void RenewFrameSubscription(bool is_still_tracking); // Called whenever the render widget is resized. void UpdateCaptureSize(); @@ -300,7 +297,7 @@ const int initial_main_render_frame_id_; // Tracks events and calls back to RenewFrameSubscription() to maintain - // capture on the correct RenderWidgetHost. + // capture on the correct RenderWidgetHostView. const scoped_refptr<WebContentsTracker> tracker_; // Set to false to prevent the capture size from automatically adjusting in @@ -404,21 +401,17 @@ } ContentCaptureSubscription::ContentCaptureSubscription( - const RenderWidgetHost& source, + base::WeakPtr<RenderWidgetHostViewBase> source_view, const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy, const CaptureCallback& capture_callback) - : render_process_id_(source.GetProcess()->GetID()), - render_widget_id_(source.GetRoutingID()), - capture_callback_(capture_callback) { + : source_view_(source_view), capture_callback_(capture_callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(source_view_); - RenderWidgetHostView* const view = source.GetView(); #if defined(USE_AURA) || defined(OS_MACOSX) - if (view) { - cursor_renderer_ = CursorRenderer::Create(view->GetNativeView()); - window_activity_tracker_ = - WindowActivityTracker::Create(view->GetNativeView()); - } + cursor_renderer_ = CursorRenderer::Create(source_view_->GetNativeView()); + window_activity_tracker_ = + WindowActivityTracker::Create(source_view_->GetNativeView()); #endif refresh_subscriber_.reset(new FrameSubscriber( media::VideoCaptureOracle::kActiveRefreshRequest, oracle_proxy, @@ -435,16 +428,14 @@ // Subscribe to compositor updates. These will be serviced directly by the // oracle. - if (view) { - std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber( - new FrameSubscriber( - media::VideoCaptureOracle::kCompositorUpdate, oracle_proxy, - cursor_renderer_ ? cursor_renderer_->GetWeakPtr() - : base::WeakPtr<CursorRenderer>(), - window_activity_tracker_ ? window_activity_tracker_->GetWeakPtr() - : base::WeakPtr<WindowActivityTracker>())); - view->BeginFrameSubscription(std::move(subscriber)); - } + std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber( + new FrameSubscriber( + media::VideoCaptureOracle::kCompositorUpdate, oracle_proxy, + cursor_renderer_ ? cursor_renderer_->GetWeakPtr() + : base::WeakPtr<CursorRenderer>(), + window_activity_tracker_ ? window_activity_tracker_->GetWeakPtr() + : base::WeakPtr<WindowActivityTracker>())); + source_view_->BeginFrameSubscription(std::move(subscriber)); // Subscribe to mouse movement and mouse cursor update events. if (window_activity_tracker_) { @@ -462,11 +453,13 @@ return; DCHECK_CURRENTLY_ON(BrowserThread::UI); - RenderWidgetHost* const source = - RenderWidgetHost::FromID(render_process_id_, render_widget_id_); - RenderWidgetHostView* const view = source ? source->GetView() : NULL; - if (view) - view->EndFrameSubscription(); + // If the RWHV weak pointer is still valid, make sure the view is still + // associated with a RWH before attempting to end the frame subscription. This + // is because a null RWH indicates the RWHV has had its Destroy() method + // called, which makes it invalid to call any of its methods that assume the + // compositor is present. + if (source_view_ && source_view_->GetRenderWidgetHost()) + source_view_->EndFrameSubscription(); } void ContentCaptureSubscription::MaybeCaptureForRefresh() { @@ -641,7 +634,7 @@ return; frame_capture_active_ = false; if (IsStarted()) - RenewFrameSubscription(true); + RenewFrameSubscription(tracker_->is_still_tracking()); } void WebContentsCaptureMachine::Resume() { @@ -656,7 +649,7 @@ return; frame_capture_active_ = true; if (IsStarted()) - RenewFrameSubscription(true); + RenewFrameSubscription(tracker_->is_still_tracking()); } void WebContentsCaptureMachine::Stop(const base::Closure& callback) { @@ -714,9 +707,8 @@ deliver_frame_cb) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - RenderWidgetHost* rwh = tracker_->GetTargetRenderWidgetHost(); - RenderWidgetHostViewBase* view = - rwh ? static_cast<RenderWidgetHostViewBase*>(rwh->GetView()) : NULL; + auto* const view = + static_cast<RenderWidgetHostViewBase*>(tracker_->GetTargetView()); if (!view) { deliver_frame_cb.Run(base::TimeTicks(), gfx::Rect(), false); return; @@ -736,13 +728,15 @@ ? gfx::Size() : media::ComputeLetterboxRegion(target->visible_rect(), view_size) .size(); - rwh->CopyFromBackingStore( - gfx::Rect(), - fitted_size, // Size here is a request not always honored. - base::Bind(&WebContentsCaptureMachine::DidCopyFromBackingStore, - weak_ptr_factory_.GetWeakPtr(), start_time, target, - deliver_frame_cb), - kN32_SkColorType); + if (auto* rwh = view->GetRenderWidgetHost()) { + rwh->CopyFromBackingStore( + gfx::Rect(), + fitted_size, // Size here is a request not always honored. + base::Bind(&WebContentsCaptureMachine::DidCopyFromBackingStore, + weak_ptr_factory_.GetWeakPtr(), start_time, target, + deliver_frame_cb), + kN32_SkColorType); + } } } @@ -795,9 +789,7 @@ // render widget to the "preferred size," the widget will be physically // rendered at the exact capture size, thereby eliminating unnecessary scaling // operations in the graphics pipeline. - RenderWidgetHost* const rwh = tracker_->GetTargetRenderWidgetHost(); - RenderWidgetHostView* const rwhv = rwh ? rwh->GetView() : NULL; - if (rwhv) { + if (auto* rwhv = tracker_->GetTargetView()) { const gfx::NativeView view = rwhv->GetNativeView(); const float scale = ui::GetScaleFactorForNativeView(view); if (scale > 1.0f) { @@ -849,20 +841,16 @@ deliver_frame_cb.Run(start_time, region_in_frame, success); } -void WebContentsCaptureMachine::RenewFrameSubscription(bool had_target) { +void WebContentsCaptureMachine::RenewFrameSubscription(bool is_still_tracking) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - RenderWidgetHost* const rwh = - had_target ? tracker_->GetTargetRenderWidgetHost() : nullptr; - // Always destroy the old subscription before creating a new one. if (subscription_) { - DVLOG(1) << "Cancelling existing ContentCaptureSubscription."; + DVLOG(1) << "Cancelling existing subscription."; subscription_.reset(); } - if (!rwh) { - DVLOG(1) << "Cannot renew ContentCaptureSubscription: no RWH target."; + if (!is_still_tracking) { if (IsStarted()) { // Tracking of WebContents and/or its main frame has failed before Stop() // was called, so report this as an error: @@ -872,12 +860,23 @@ return; } - if (frame_capture_active_) { - DVLOG(1) << "Renewing ContentCaptureSubscription to RWH@" << rwh; - subscription_.reset(new ContentCaptureSubscription( - *rwh, oracle_proxy_, base::Bind(&WebContentsCaptureMachine::Capture, - weak_ptr_factory_.GetWeakPtr()))); + if (!frame_capture_active_) { + DVLOG(1) << "Not renewing subscription: Frame capture is suspended."; + return; } + + auto* const view = + static_cast<RenderWidgetHostViewBase*>(tracker_->GetTargetView()); + if (!view) { + DVLOG(1) << "Cannot renew subscription: No view to capture."; + return; + } + + DVLOG(1) << "Renewing subscription to RenderWidgetHostView@" << view; + subscription_.reset(new ContentCaptureSubscription( + view->GetWeakPtr(), oracle_proxy_, + base::Bind(&WebContentsCaptureMachine::Capture, + weak_ptr_factory_.GetWeakPtr()))); } void WebContentsCaptureMachine::UpdateCaptureSize() { @@ -885,8 +884,7 @@ if (!oracle_proxy_) return; - RenderWidgetHost* const rwh = tracker_->GetTargetRenderWidgetHost(); - RenderWidgetHostView* const view = rwh ? rwh->GetView() : nullptr; + RenderWidgetHostView* const view = tracker_->GetTargetView(); if (!view) return;
diff --git a/content/browser/renderer_host/media/OWNERS b/content/browser/renderer_host/media/OWNERS index 8ac77eba..a8e56056 100644 --- a/content/browser/renderer_host/media/OWNERS +++ b/content/browser/renderer_host/media/OWNERS
@@ -6,4 +6,5 @@ per-file gpu_memory*=mcasas@chromium.org per-file shared_memory*=mcasas@chromium.org -per-file video_capture*=mcasas@chromium.org +per-file video_*=mcasas@chromium.org +per-file video_*=chfremer@chromium.org
diff --git a/content/browser/renderer_host/media/video_capture_controller.cc b/content/browser/renderer_host/media/video_capture_controller.cc index fd171279..ac5bc721 100644 --- a/content/browser/renderer_host/media/video_capture_controller.cc +++ b/content/browser/renderer_host/media/video_capture_controller.cc
@@ -18,12 +18,11 @@ #include "build/build_config.h" #include "components/display_compositor/gl_helper.h" #include "content/browser/renderer_host/media/media_stream_manager.h" -#include "content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h" #include "content/browser/renderer_host/media/video_capture_manager.h" #include "content/public/browser/browser_thread.h" #include "content/public/common/content_switches.h" #include "media/base/video_frame.h" -#include "media/capture/video/video_capture_buffer_pool_impl.h" +#include "media/capture/video/video_capture_buffer_pool.h" #include "media/capture/video/video_capture_buffer_tracker_factory_impl.h" #include "media/capture/video/video_capture_device_client.h" @@ -46,50 +45,6 @@ name, \ (height) ? ((width) * 100) / (height) : kInfiniteRatio); -std::unique_ptr<media::VideoCaptureJpegDecoder> CreateGpuJpegDecoder( - const media::VideoCaptureJpegDecoder::DecodeDoneCB& decode_done_cb) { - return base::MakeUnique<VideoCaptureGpuJpegDecoder>(decode_done_cb); -} - -// Decorator for media::VideoFrameReceiver that forwards all incoming calls -// to the Browser IO thread. -class VideoFrameReceiverOnIOThread : public media::VideoFrameReceiver { - public: - explicit VideoFrameReceiverOnIOThread( - const base::WeakPtr<VideoFrameReceiver>& receiver) - : receiver_(receiver) {} - - void OnIncomingCapturedVideoFrame( - std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer, - scoped_refptr<media::VideoFrame> frame) override { - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&VideoFrameReceiver::OnIncomingCapturedVideoFrame, receiver_, - base::Passed(&buffer), std::move(frame))); - } - - void OnError() override { - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&VideoFrameReceiver::OnError, receiver_)); - } - - void OnLog(const std::string& message) override { - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&VideoFrameReceiver::OnLog, receiver_, message)); - } - - void OnBufferDestroyed(int buffer_id_to_drop) override { - BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::Bind(&VideoFrameReceiver::OnBufferDestroyed, - receiver_, buffer_id_to_drop)); - } - - private: - base::WeakPtr<VideoFrameReceiver> receiver_; -}; - } // anonymous namespace struct VideoCaptureController::ControllerClient { @@ -140,12 +95,12 @@ int buffer_id, int frame_feedback_id, media::VideoFrameConsumerFeedbackObserver* consumer_feedback_observer, - scoped_refptr<media::VideoCaptureBufferPool> buffer_pool, + media::FrameBufferPool* frame_buffer_pool, scoped_refptr<media::VideoFrame> frame) : buffer_id_(buffer_id), frame_feedback_id_(frame_feedback_id), consumer_feedback_observer_(consumer_feedback_observer), - buffer_pool_(std::move(buffer_pool)), + frame_buffer_pool_(frame_buffer_pool), frame_(std::move(frame)), max_consumer_utilization_( media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded), @@ -166,7 +121,8 @@ void VideoCaptureController::BufferState::IncreaseConsumerCount() { if (consumer_hold_count_ == 0) - buffer_pool_->HoldForConsumers(buffer_id_, 1); + if (frame_buffer_pool_ != nullptr) + frame_buffer_pool_->SetBufferHold(buffer_id_); consumer_hold_count_++; } @@ -179,7 +135,8 @@ consumer_feedback_observer_->OnUtilizationReport( frame_feedback_id_, max_consumer_utilization_); } - buffer_pool_->RelinquishConsumerHold(buffer_id_, 1); + if (frame_buffer_pool_ != nullptr) + frame_buffer_pool_->ReleaseBufferHold(buffer_id_); max_consumer_utilization_ = media::VideoFrameConsumerFeedbackObserver::kNoUtilizationRecorded; } @@ -194,10 +151,13 @@ consumer_feedback_observer_ = consumer_feedback_observer; } -VideoCaptureController::VideoCaptureController(int max_buffers) - : buffer_pool_(new media::VideoCaptureBufferPoolImpl( - base::MakeUnique<media::VideoCaptureBufferTrackerFactoryImpl>(), - max_buffers)), +void VideoCaptureController::BufferState::SetFrameBufferPool( + media::FrameBufferPool* frame_buffer_pool) { + frame_buffer_pool_ = frame_buffer_pool; +} + +VideoCaptureController::VideoCaptureController() + : frame_buffer_pool_(nullptr), consumer_feedback_observer_(nullptr), state_(VIDEO_CAPTURE_STATE_STARTED), has_received_frames_(false), @@ -205,11 +165,22 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); } +VideoCaptureController::~VideoCaptureController() = default; + base::WeakPtr<VideoCaptureController> VideoCaptureController::GetWeakPtrForIOThread() { return weak_ptr_factory_.GetWeakPtr(); } +void VideoCaptureController::SetFrameBufferPool( + std::unique_ptr<media::FrameBufferPool> frame_buffer_pool) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + frame_buffer_pool_ = std::move(frame_buffer_pool); + // Update existing BufferState entries. + for (auto& entry : buffer_id_to_state_map_) + entry.second.SetFrameBufferPool(frame_buffer_pool_.get()); +} + void VideoCaptureController::SetConsumerFeedbackObserver( std::unique_ptr<media::VideoFrameConsumerFeedbackObserver> consumer_feedback_observer) { @@ -220,18 +191,6 @@ entry.second.SetConsumerFeedbackObserver(consumer_feedback_observer_.get()); } -std::unique_ptr<media::VideoCaptureDevice::Client> -VideoCaptureController::NewDeviceClient() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - return base::MakeUnique<media::VideoCaptureDeviceClient>( - base::MakeUnique<VideoFrameReceiverOnIOThread>( - this->GetWeakPtrForIOThread()), - buffer_pool_, - base::Bind(&CreateGpuJpegDecoder, - base::Bind(&VideoFrameReceiver::OnIncomingCapturedVideoFrame, - this->GetWeakPtrForIOThread()))); -} - void VideoCaptureController::AddClient( VideoCaptureControllerID id, VideoCaptureControllerEventHandler* event_handler, @@ -378,7 +337,6 @@ VideoCaptureControllerID id, VideoCaptureControllerEventHandler* event_handler, int buffer_id, - const gpu::SyncToken& sync_token, double consumer_resource_utilization) { DCHECK_CURRENTLY_ON(BrowserThread::IO); @@ -410,13 +368,11 @@ return video_capture_format_; } -VideoCaptureController::~VideoCaptureController() { -} - void VideoCaptureController::OnIncomingCapturedVideoFrame( std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer, scoped_refptr<VideoFrame> frame) { DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(frame_buffer_pool_); const int buffer_id = buffer->id(); DCHECK_NE(buffer_id, media::VideoCaptureBufferPool::kInvalidId); @@ -426,7 +382,7 @@ .insert(std::make_pair( buffer_id, BufferState(buffer_id, buffer->frame_feedback_id(), consumer_feedback_observer_.get(), - buffer_pool_, frame))) + frame_buffer_pool_.get(), frame))) .first; BufferState& buffer_state = it->second; DCHECK(buffer_state.HasZeroConsumerHoldCount()); @@ -519,6 +475,7 @@ void VideoCaptureController::OnBufferDestroyed(int buffer_id_to_drop) { DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(frame_buffer_pool_); for (const auto& client : controller_clients_) { if (client->session_closed) @@ -546,7 +503,7 @@ const int buffer_id = buffer->id(); mojo::ScopedSharedBufferHandle handle = - buffer_pool_->GetHandleForTransit(buffer_id); + frame_buffer_pool_->GetHandleForTransit(buffer_id); client->event_handler->OnBufferCreated(client->controller_id, std::move(handle), buffer->mapped_size(), buffer_id);
diff --git a/content/browser/renderer_host/media/video_capture_controller.h b/content/browser/renderer_host/media/video_capture_controller.h index b1a455f..4be8085 100644 --- a/content/browser/renderer_host/media/video_capture_controller.h +++ b/content/browser/renderer_host/media/video_capture_controller.h
@@ -55,23 +55,27 @@ #include "media/capture/video_capture_types.h" namespace media { -class VideoCaptureBufferPool; +class FrameBufferPool; } namespace content { class CONTENT_EXPORT VideoCaptureController : public media::VideoFrameReceiver { public: - // |max_buffers| is the maximum number of video frame buffers in-flight at any - // one time. This value should be based on the logical capacity of the - // capture pipeline, and not on hardware performance. For example, tab - // capture requires more buffers than webcam capture because the pipeline is - // longer (it includes read-backs pending in the GPU pipeline). - explicit VideoCaptureController(int max_buffers); + VideoCaptureController(); ~VideoCaptureController() override; base::WeakPtr<VideoCaptureController> GetWeakPtrForIOThread(); + // Factory code creating instances of VideoCaptureController must set a + // FrameBufferPool before any of the media::VideoFrameReceiver are used. + // Setting the observer is done in this method separate from the constructor + // in order to allow use the media::VideoFrameReceiver methods + // before the observer can be provided. (This is the case with + // VideoCaptureManager). + void SetFrameBufferPool( + std::unique_ptr<media::FrameBufferPool> frame_buffer_pool); + // Factory code creating instances of VideoCaptureController may optionally // set a VideoFrameConsumerFeedbackObserver. Setting the observer is done in // this method separate from the constructor to allow clients to create and @@ -80,10 +84,6 @@ void SetConsumerFeedbackObserver( std::unique_ptr<media::VideoFrameConsumerFeedbackObserver> observer); - // Return a new VideoCaptureDeviceClient to forward capture events to this - // instance. - std::unique_ptr<media::VideoCaptureDevice::Client> NewDeviceClient(); - // Start video capturing and try to use the resolution specified in |params|. // Buffers will be shared to the client as necessary. The client will continue // to receive frames from the device until RemoveClient() is called. @@ -120,15 +120,12 @@ void StopSession(int session_id); // Return a buffer with id |buffer_id| previously given in - // VideoCaptureControllerEventHandler::OnBufferReady. In the case that the - // buffer was backed by a texture, |sync_token| will be waited on before - // destroying or recycling the texture, to synchronize with texture users in - // the renderer process. If the consumer provided resource utilization + // VideoCaptureControllerEventHandler::OnBufferReady. + // If the consumer provided resource utilization // feedback, this will be passed here (-1.0 indicates no feedback). void ReturnBuffer(VideoCaptureControllerID id, VideoCaptureControllerEventHandler* event_handler, int buffer_id, - const gpu::SyncToken& sync_token, double consumer_resource_utilization); const media::VideoCaptureFormat& GetVideoCaptureFormat() const; @@ -153,7 +150,7 @@ int buffer_id, int frame_feedback_id, media::VideoFrameConsumerFeedbackObserver* consumer_feedback_observer, - scoped_refptr<media::VideoCaptureBufferPool> buffer_pool, + media::FrameBufferPool* frame_buffer_pool, scoped_refptr<media::VideoFrame> frame); ~BufferState(); BufferState(const BufferState& other); @@ -163,12 +160,13 @@ bool HasZeroConsumerHoldCount(); void SetConsumerFeedbackObserver( media::VideoFrameConsumerFeedbackObserver* consumer_feedback_observer); + void SetFrameBufferPool(media::FrameBufferPool* frame_buffer_pool); private: const int buffer_id_; const int frame_feedback_id_; media::VideoFrameConsumerFeedbackObserver* consumer_feedback_observer_; - const scoped_refptr<media::VideoCaptureBufferPool> buffer_pool_; + media::FrameBufferPool* frame_buffer_pool_; const scoped_refptr<media::VideoFrame> frame_; double max_consumer_utilization_; int consumer_hold_count_; @@ -188,8 +186,7 @@ ControllerClient* FindClient(int session_id, const ControllerClients& clients); - // The pool of shared-memory buffers used for capturing. - const scoped_refptr<media::VideoCaptureBufferPool> buffer_pool_; + std::unique_ptr<media::FrameBufferPool> frame_buffer_pool_; std::unique_ptr<media::VideoFrameConsumerFeedbackObserver> consumer_feedback_observer_;
diff --git a/content/browser/renderer_host/media/video_capture_controller_unittest.cc b/content/browser/renderer_host/media/video_capture_controller_unittest.cc index 8a28593d..e9e59c4 100644 --- a/content/browser/renderer_host/media/video_capture_controller_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_controller_unittest.cc
@@ -24,11 +24,16 @@ #include "base/threading/thread_task_runner_handle.h" #include "content/browser/renderer_host/media/media_stream_provider.h" #include "content/browser/renderer_host/media/video_capture_controller_event_handler.h" +#include "content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h" #include "content/browser/renderer_host/media/video_capture_manager.h" +#include "content/browser/renderer_host/media/video_frame_receiver_on_io_thread.h" #include "content/common/media/media_stream_options.h" #include "content/public/test/test_browser_thread_bundle.h" #include "media/base/video_frame_metadata.h" #include "media/base/video_util.h" +#include "media/capture/video/video_capture_buffer_pool_impl.h" +#include "media/capture/video/video_capture_buffer_tracker_factory_impl.h" +#include "media/capture/video/video_capture_device_client.h" #include "media/capture/video_capture_types.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -41,13 +46,17 @@ namespace content { +std::unique_ptr<media::VideoCaptureJpegDecoder> CreateGpuJpegDecoder( + const media::VideoCaptureJpegDecoder::DecodeDoneCB& decode_done_cb) { + return base::MakeUnique<content::VideoCaptureGpuJpegDecoder>(decode_done_cb); +} + class MockVideoCaptureControllerEventHandler : public VideoCaptureControllerEventHandler { public: explicit MockVideoCaptureControllerEventHandler( VideoCaptureController* controller) - : controller_(controller), - resource_utilization_(-1.0) {} + : controller_(controller), resource_utilization_(-1.0) {} ~MockVideoCaptureControllerEventHandler() override {} // These mock methods are delegated to by our fake implementation of @@ -58,12 +67,11 @@ MOCK_METHOD1(DoEnded, void(VideoCaptureControllerID)); MOCK_METHOD1(DoError, void(VideoCaptureControllerID)); - void OnError(VideoCaptureControllerID id) override { - DoError(id); - } + void OnError(VideoCaptureControllerID id) override { DoError(id); } void OnBufferCreated(VideoCaptureControllerID id, mojo::ScopedSharedBufferHandle handle, - int length, int buffer_id) override { + int length, + int buffer_id) override { DoBufferCreated(id); } void OnBufferDestroyed(VideoCaptureControllerID id, int buffer_id) override { @@ -78,10 +86,9 @@ media::VideoFrameMetadata::REFERENCE_TIME, &reference_time)); DoBufferReady(id, frame->coded_size()); base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&VideoCaptureController::ReturnBuffer, - base::Unretained(controller_), id, this, buffer_id, - gpu::SyncToken(), resource_utilization_)); + FROM_HERE, base::Bind(&VideoCaptureController::ReturnBuffer, + base::Unretained(controller_), id, this, + buffer_id, resource_utilization_)); } void OnEnded(VideoCaptureControllerID id) override { DoEnded(id); @@ -104,6 +111,14 @@ void(int frame_feedback_id, double utilization)); }; +class MockFrameBufferPool : public media::FrameBufferPool { + public: + MOCK_METHOD1(SetBufferHold, void(int buffer_id)); + MOCK_METHOD1(ReleaseBufferHold, void(int buffer_id)); + MOCK_METHOD1(GetHandleForTransit, + mojo::ScopedSharedBufferHandle(int buffer_id)); +}; + // Test class. class VideoCaptureControllerTest : public testing::Test, @@ -116,8 +131,22 @@ static const int kPoolSize = 3; void SetUp() override { - controller_.reset(new VideoCaptureController(kPoolSize)); - device_ = controller_->NewDeviceClient(); + scoped_refptr<media::VideoCaptureBufferPool> buffer_pool( + new media::VideoCaptureBufferPoolImpl( + base::MakeUnique<media::VideoCaptureBufferTrackerFactoryImpl>(), + kPoolSize)); + controller_.reset(new VideoCaptureController()); + device_client_.reset(new media::VideoCaptureDeviceClient( + base::MakeUnique<VideoFrameReceiverOnIOThread>( + controller_->GetWeakPtrForIOThread()), + buffer_pool, + base::Bind( + &CreateGpuJpegDecoder, + base::Bind(&media::VideoFrameReceiver::OnIncomingCapturedVideoFrame, + controller_->GetWeakPtrForIOThread())))); + auto frame_receiver_observer = base::MakeUnique<MockFrameBufferPool>(); + mock_frame_receiver_observer_ = frame_receiver_observer.get(); + controller_->SetFrameBufferPool(std::move(frame_receiver_observer)); auto consumer_feedback_observer = base::MakeUnique<MockConsumerFeedbackObserver>(); mock_consumer_feedback_observer_ = consumer_feedback_observer.get(); @@ -148,7 +177,8 @@ std::unique_ptr<MockVideoCaptureControllerEventHandler> client_a_; std::unique_ptr<MockVideoCaptureControllerEventHandler> client_b_; std::unique_ptr<VideoCaptureController> controller_; - std::unique_ptr<media::VideoCaptureDevice::Client> device_; + std::unique_ptr<media::VideoCaptureDevice::Client> device_client_; + MockFrameBufferPool* mock_frame_receiver_observer_; MockConsumerFeedbackObserver* mock_consumer_feedback_observer_; private: @@ -300,13 +330,13 @@ // side effect this will cause the first buffer to be shared with clients. uint8_t buffer_no = 1; const int arbitrary_frame_feedback_id = 101; - ASSERT_EQ(0.0, device_->GetBufferPoolUtilization()); + ASSERT_EQ(0.0, device_client_->GetBufferPoolUtilization()); std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer( - device_->ReserveOutputBuffer(capture_resolution, format, - media::PIXEL_STORAGE_CPU, - arbitrary_frame_feedback_id)); + device_client_->ReserveOutputBuffer(capture_resolution, format, + media::PIXEL_STORAGE_CPU, + arbitrary_frame_feedback_id)); ASSERT_TRUE(buffer.get()); - ASSERT_EQ(1.0 / kPoolSize, device_->GetBufferPoolUtilization()); + ASSERT_EQ(1.0 / kPoolSize, device_client_->GetBufferPoolUtilization()); memset(buffer->data(), buffer_no++, buffer->mapped_size()); { InSequence s; @@ -333,30 +363,37 @@ media::VideoFrameMetadata::RESOURCE_UTILIZATION)); client_a_->resource_utilization_ = 0.5; client_b_->resource_utilization_ = -1.0; - - // Expect VideoCaptureController to call the load observer with a - // resource utilization of 0.5 (the largest of all reported values). - EXPECT_CALL(*mock_consumer_feedback_observer_, - OnUtilizationReport(arbitrary_frame_feedback_id, 0.5)) - .Times(1); + { + InSequence s; + EXPECT_CALL(*mock_frame_receiver_observer_, SetBufferHold(buffer->id())) + .Times(1); + // Expect VideoCaptureController to call the load observer with a + // resource utilization of 0.5 (the largest of all reported values). + EXPECT_CALL(*mock_consumer_feedback_observer_, + OnUtilizationReport(arbitrary_frame_feedback_id, 0.5)) + .Times(1); + EXPECT_CALL(*mock_frame_receiver_observer_, ReleaseBufferHold(buffer->id())) + .Times(1); + } video_frame->metadata()->SetTimeTicks( media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks()); - device_->OnIncomingCapturedVideoFrame(std::move(buffer), video_frame); + device_client_->OnIncomingCapturedVideoFrame(std::move(buffer), video_frame); base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(client_a_.get()); Mock::VerifyAndClearExpectations(client_b_.get()); Mock::VerifyAndClearExpectations(mock_consumer_feedback_observer_); + Mock::VerifyAndClearExpectations(mock_frame_receiver_observer_); // Second buffer which ought to use the same shared memory buffer. In this // case pretend that the Buffer pointer is held by the device for a long // delay. This shouldn't affect anything. const int arbitrary_frame_feedback_id_2 = 102; std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer2 = - device_->ReserveOutputBuffer(capture_resolution, format, - media::PIXEL_STORAGE_CPU, - arbitrary_frame_feedback_id_2); + device_client_->ReserveOutputBuffer(capture_resolution, format, + media::PIXEL_STORAGE_CPU, + arbitrary_frame_feedback_id_2); ASSERT_TRUE(buffer2.get()); memset(buffer2->data(), buffer_no++, buffer2->mapped_size()); video_frame = WrapBuffer(capture_resolution, @@ -367,11 +404,21 @@ media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks()); // Expect VideoCaptureController to call the load observer with a // resource utilization of 3.14 (the largest of all reported values). - EXPECT_CALL(*mock_consumer_feedback_observer_, - OnUtilizationReport(arbitrary_frame_feedback_id_2, 3.14)) - .Times(1); + { + InSequence s; + EXPECT_CALL(*mock_frame_receiver_observer_, SetBufferHold(buffer2->id())) + .Times(1); + // Expect VideoCaptureController to call the load observer with a + // resource utilization of 3.14 (the largest of all reported values). + EXPECT_CALL(*mock_consumer_feedback_observer_, + OnUtilizationReport(arbitrary_frame_feedback_id_2, 3.14)) + .Times(1); + EXPECT_CALL(*mock_frame_receiver_observer_, + ReleaseBufferHold(buffer2->id())) + .Times(1); + } - device_->OnIncomingCapturedVideoFrame(std::move(buffer2), video_frame); + device_client_->OnIncomingCapturedVideoFrame(std::move(buffer2), video_frame); // The buffer should be delivered to the clients in any order. { @@ -396,6 +443,7 @@ Mock::VerifyAndClearExpectations(client_a_.get()); Mock::VerifyAndClearExpectations(client_b_.get()); Mock::VerifyAndClearExpectations(mock_consumer_feedback_observer_); + Mock::VerifyAndClearExpectations(mock_frame_receiver_observer_); // Add a fourth client now that some buffers have come through. controller_->AddClient(client_b_route_2, @@ -408,9 +456,9 @@ for (int i = 0; i < kPoolSize; i++) { const int arbitrary_frame_feedback_id = 200 + i; std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer = - device_->ReserveOutputBuffer(capture_resolution, format, - media::PIXEL_STORAGE_CPU, - arbitrary_frame_feedback_id); + device_client_->ReserveOutputBuffer(capture_resolution, format, + media::PIXEL_STORAGE_CPU, + arbitrary_frame_feedback_id); ASSERT_TRUE(buffer.get()); memset(buffer->data(), buffer_no++, buffer->mapped_size()); video_frame = WrapBuffer(capture_resolution, @@ -418,10 +466,11 @@ ASSERT_TRUE(video_frame); video_frame->metadata()->SetTimeTicks( media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks()); - device_->OnIncomingCapturedVideoFrame(std::move(buffer), video_frame); + device_client_->OnIncomingCapturedVideoFrame(std::move(buffer), + video_frame); } // ReserveOutputBuffer ought to fail now, because the pool is depleted. - ASSERT_FALSE(device_ + ASSERT_FALSE(device_client_ ->ReserveOutputBuffer(capture_resolution, format, media::PIXEL_STORAGE_CPU, arbitrary_frame_feedback_id) @@ -456,9 +505,9 @@ controller_->StopSession(300); // Queue up another buffer. std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer3 = - device_->ReserveOutputBuffer(capture_resolution, format, - media::PIXEL_STORAGE_CPU, - arbitrary_frame_feedback_id); + device_client_->ReserveOutputBuffer(capture_resolution, format, + media::PIXEL_STORAGE_CPU, + arbitrary_frame_feedback_id); ASSERT_TRUE(buffer3.get()); memset(buffer3->data(), buffer_no++, buffer3->mapped_size()); video_frame = WrapBuffer(capture_resolution, @@ -466,12 +515,12 @@ ASSERT_TRUE(video_frame); video_frame->metadata()->SetTimeTicks( media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks()); - device_->OnIncomingCapturedVideoFrame(std::move(buffer3), video_frame); + device_client_->OnIncomingCapturedVideoFrame(std::move(buffer3), video_frame); std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer4 = - device_->ReserveOutputBuffer(capture_resolution, format, - media::PIXEL_STORAGE_CPU, - arbitrary_frame_feedback_id); + device_client_->ReserveOutputBuffer(capture_resolution, format, + media::PIXEL_STORAGE_CPU, + arbitrary_frame_feedback_id); { // Kill A2 via session close (posts a task to disconnect, but A2 must not // be sent either of these two buffers). @@ -485,7 +534,7 @@ ASSERT_TRUE(video_frame); video_frame->metadata()->SetTimeTicks( media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks()); - device_->OnIncomingCapturedVideoFrame(std::move(buffer4), video_frame); + device_client_->OnIncomingCapturedVideoFrame(std::move(buffer4), video_frame); // B2 is the only client left, and is the only one that should // get the buffer. EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2, capture_resolution)) @@ -515,7 +564,7 @@ // Start with one client. controller_->AddClient(route_id, client_a_.get(), 100, session_100); - device_->OnError(FROM_HERE, "Test Error"); + device_client_->OnError(FROM_HERE, "Test Error"); EXPECT_CALL(*client_a_, DoError(route_id)).Times(1); base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(client_a_.get()); @@ -529,16 +578,16 @@ const int arbitrary_frame_feedback_id = 101; std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer( - device_->ReserveOutputBuffer(capture_resolution, media::PIXEL_FORMAT_I420, - media::PIXEL_STORAGE_CPU, - arbitrary_frame_feedback_id)); + device_client_->ReserveOutputBuffer( + capture_resolution, media::PIXEL_FORMAT_I420, + media::PIXEL_STORAGE_CPU, arbitrary_frame_feedback_id)); ASSERT_TRUE(buffer.get()); scoped_refptr<media::VideoFrame> video_frame = WrapBuffer(capture_resolution, static_cast<uint8_t*>(buffer->data())); ASSERT_TRUE(video_frame); video_frame->metadata()->SetTimeTicks( media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks()); - device_->OnIncomingCapturedVideoFrame(std::move(buffer), video_frame); + device_client_->OnIncomingCapturedVideoFrame(std::move(buffer), video_frame); base::RunLoop().RunUntilIdle(); } @@ -568,18 +617,18 @@ const gfx::Size dims(320, 240); const int arbitrary_frame_feedback_id = 101; std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer( - device_->ReserveOutputBuffer(dims, media::PIXEL_FORMAT_I420, - media::PIXEL_STORAGE_CPU, - arbitrary_frame_feedback_id)); + device_client_->ReserveOutputBuffer(dims, media::PIXEL_FORMAT_I420, + media::PIXEL_STORAGE_CPU, + arbitrary_frame_feedback_id)); ASSERT_TRUE(buffer.get()); scoped_refptr<media::VideoFrame> video_frame = WrapBuffer(dims, static_cast<uint8_t*>(buffer->data())); ASSERT_TRUE(video_frame); - device_->OnError(FROM_HERE, "Test Error"); + device_client_->OnError(FROM_HERE, "Test Error"); video_frame->metadata()->SetTimeTicks( media::VideoFrameMetadata::REFERENCE_TIME, base::TimeTicks()); - device_->OnIncomingCapturedVideoFrame(std::move(buffer), video_frame); + device_client_->OnIncomingCapturedVideoFrame(std::move(buffer), video_frame); EXPECT_CALL(*client_a_, DoError(route_id)).Times(1); base::RunLoop().RunUntilIdle();
diff --git a/content/browser/renderer_host/media/video_capture_device_client_unittest.cc b/content/browser/renderer_host/media/video_capture_device_client_unittest.cc index 020854b..e2a6a82 100644 --- a/content/browser/renderer_host/media/video_capture_device_client_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_device_client_unittest.cc
@@ -16,9 +16,12 @@ #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "content/browser/renderer_host/media/video_capture_controller.h" +#include "content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h" +#include "content/browser/renderer_host/media/video_frame_receiver_on_io_thread.h" #include "content/public/test/test_browser_thread_bundle.h" #include "media/base/limits.h" -#include "media/capture/video/video_capture_buffer_pool.h" +#include "media/capture/video/video_capture_buffer_pool_impl.h" +#include "media/capture/video/video_capture_buffer_tracker_factory_impl.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -33,8 +36,7 @@ class MockVideoCaptureController : public VideoCaptureController { public: - explicit MockVideoCaptureController(int max_buffers) - : VideoCaptureController(max_buffers) {} + explicit MockVideoCaptureController() : VideoCaptureController() {} ~MockVideoCaptureController() override {} MOCK_METHOD1(MockOnIncomingCapturedVideoFrame, void(const gfx::Size&)); @@ -49,6 +51,11 @@ } }; +std::unique_ptr<media::VideoCaptureJpegDecoder> CreateGpuJpegDecoder( + const media::VideoCaptureJpegDecoder::DecodeDoneCB& decode_done_cb) { + return base::MakeUnique<content::VideoCaptureGpuJpegDecoder>(decode_done_cb); +} + // Note that this test does not exercise the class VideoCaptureDeviceClient // in isolation. The "unit under test" is an instance of // VideoCaptureDeviceClient with some context that is specific to @@ -57,17 +64,29 @@ class VideoCaptureDeviceClientTest : public ::testing::Test { public: VideoCaptureDeviceClientTest() - : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), - controller_(new MockVideoCaptureController(1)), - device_client_(controller_->NewDeviceClient()) {} + : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) { + scoped_refptr<media::VideoCaptureBufferPoolImpl> buffer_pool( + new media::VideoCaptureBufferPoolImpl( + base::MakeUnique<media::VideoCaptureBufferTrackerFactoryImpl>(), + 1)); + controller_ = base::MakeUnique<MockVideoCaptureController>(); + device_client_ = base::MakeUnique<media::VideoCaptureDeviceClient>( + base::MakeUnique<VideoFrameReceiverOnIOThread>( + controller_->GetWeakPtrForIOThread()), + buffer_pool, + base::Bind( + &CreateGpuJpegDecoder, + base::Bind(&media::VideoFrameReceiver::OnIncomingCapturedVideoFrame, + controller_->GetWeakPtrForIOThread()))); + } ~VideoCaptureDeviceClientTest() override {} void TearDown() override { base::RunLoop().RunUntilIdle(); } protected: const content::TestBrowserThreadBundle thread_bundle_; - const std::unique_ptr<MockVideoCaptureController> controller_; - const std::unique_ptr<media::VideoCaptureDevice::Client> device_client_; + std::unique_ptr<MockVideoCaptureController> controller_; + std::unique_ptr<media::VideoCaptureDeviceClient> device_client_; private: DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceClientTest);
diff --git a/content/browser/renderer_host/media/video_capture_host.cc b/content/browser/renderer_host/media/video_capture_host.cc index bb78fd1..4c458f5 100644 --- a/content/browser/renderer_host/media/video_capture_host.cc +++ b/content/browser/renderer_host/media/video_capture_host.cc
@@ -212,7 +212,6 @@ void VideoCaptureHost::ReleaseBuffer(int32_t device_id, int32_t buffer_id, - const gpu::SyncToken& sync_token, double consumer_resource_utilization) { DCHECK_CURRENTLY_ON(BrowserThread::IO); @@ -223,7 +222,7 @@ const base::WeakPtr<VideoCaptureController>& controller = it->second; if (controller) { - controller->ReturnBuffer(controller_id, this, buffer_id, sync_token, + controller->ReturnBuffer(controller_id, this, buffer_id, consumer_resource_utilization); } }
diff --git a/content/browser/renderer_host/media/video_capture_host.h b/content/browser/renderer_host/media/video_capture_host.h index 71d6ebc3..a92ac9a 100644 --- a/content/browser/renderer_host/media/video_capture_host.h +++ b/content/browser/renderer_host/media/video_capture_host.h
@@ -64,7 +64,6 @@ void RequestRefreshFrame(int32_t device_id) override; void ReleaseBuffer(int32_t device_id, int32_t buffer_id, - const gpu::SyncToken& sync_token, double consumer_resource_utilization) override; void GetDeviceSupportedFormats( int32_t device_id,
diff --git a/content/browser/renderer_host/media/video_capture_manager.cc b/content/browser/renderer_host/media/video_capture_manager.cc index a316e94..dca1d39c 100644 --- a/content/browser/renderer_host/media/video_capture_manager.cc +++ b/content/browser/renderer_host/media/video_capture_manager.cc
@@ -27,12 +27,17 @@ #include "content/browser/media/media_internals.h" #include "content/browser/renderer_host/media/video_capture_controller.h" #include "content/browser/renderer_host/media/video_capture_controller_event_handler.h" +#include "content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h" +#include "content/browser/renderer_host/media/video_frame_receiver_on_io_thread.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/desktop_media_id.h" #include "content/public/common/media_stream_request.h" #include "media/base/bind_to_current_loop.h" #include "media/base/media_switches.h" +#include "media/capture/video/video_capture_buffer_pool_impl.h" +#include "media/capture/video/video_capture_buffer_tracker_factory_impl.h" #include "media/capture/video/video_capture_device.h" +#include "media/capture/video/video_capture_device_client.h" #include "media/capture/video/video_capture_device_factory.h" #if defined(ENABLE_SCREEN_CAPTURE) && !defined(OS_ANDROID) @@ -114,8 +119,11 @@ } } -// The maximum number of buffers in the capture pipeline. See -// VideoCaptureController ctor comments for more details. +// The maximum number of video frame buffers in-flight at any one time. This +// value should be based on the logical capacity of the capture pipeline, and +// not on hardware performance. For example, tab capture requires more buffers +// than webcam capture because the pipeline is longer (it includes read-backs +// pending in the GPU pipeline). const int kMaxNumberOfBuffers = 3; // TODO(miu): The value for tab capture should be determined programmatically. // http://crbug.com/460318 @@ -144,46 +152,51 @@ const media::VideoCaptureSessionId kFakeSessionId = -1; +std::unique_ptr<media::VideoCaptureJpegDecoder> CreateGpuJpegDecoder( + const media::VideoCaptureJpegDecoder::DecodeDoneCB& decode_done_cb) { + return base::MakeUnique<content::VideoCaptureGpuJpegDecoder>(decode_done_cb); +} + } // namespace namespace content { -// Instances of this struct go through 3 different phases during their lifetime. +// Instances of this struct go through several different phases during their +// lifetime. // Phase 1: When first created (in GetOrCreateDeviceEntry()), this consists of -// only a controller. Clients can already connect to the controller, but there -// is no device present. +// only the |video_capture_controller|. Clients can already connect to the +// controller, but there is no |buffer_pool| or |video_capture_device| present. // Phase 2: When a request to "start" the entry comes in (via -// HandleQueuedStartRequest()), a VideoCaptureDevice::Client is created -// via video_capture_controller()->NewDeviceClient() and is used to schedule the -// creation and start of a VideoCaptureDevice on the Device Thread. +// HandleQueuedStartRequest()), |buffer_pool| is created and creation of +// |video_capture_device| is scheduled to run asynchronously on the Device +// Thread. // Phase 3: As soon as the creation of the VideoCaptureDevice is complete, this // newly created VideoCaptureDevice instance is connected to the -// VideoCaptureController via SetConsumerFeedbackObserver(). -class VideoCaptureManager::DeviceEntry { +// VideoCaptureController via SetConsumerFeedbackObserver(). Furthermore, the +// |buffer_pool| is connected to the |video_capture_controller| as a +// FrameBufferPool via SetFrameBufferPool(). +// Phase 4: This phase can only be reached on Android. When the application goes +// to the background, the |video_capture_device| is asynchronously stopped and +// released on the Device Thread. The existing |buffer_pool| is kept alive, and +// all clients of |video_capture_controller| stay connected. When the +// application is resumed, we transition to Phase 2, except that the existing +// |buffer_pool| get reused instead of creating a new one. +struct VideoCaptureManager::DeviceEntry { public: DeviceEntry(MediaStreamType stream_type, const std::string& id, - std::unique_ptr<VideoCaptureController> controller, const media::VideoCaptureParams& params); ~DeviceEntry(); + std::unique_ptr<media::VideoCaptureDevice::Client> CreateDeviceClient(); + std::unique_ptr<media::FrameBufferPool> CreateFrameBufferPool(); const int serial_id; const MediaStreamType stream_type; const std::string id; const media::VideoCaptureParams parameters; - - VideoCaptureController* video_capture_controller() const; - media::VideoCaptureDevice* video_capture_device() const; - - void SetVideoCaptureDevice(std::unique_ptr<VideoCaptureDevice> device); - std::unique_ptr<VideoCaptureDevice> ReleaseVideoCaptureDevice(); - - private: - const std::unique_ptr<VideoCaptureController> video_capture_controller_; - - std::unique_ptr<VideoCaptureDevice> video_capture_device_; - - base::ThreadChecker thread_checker_; + VideoCaptureController video_capture_controller; + scoped_refptr<media::VideoCaptureBufferPool> buffer_pool; + std::unique_ptr<media::VideoCaptureDevice> video_capture_device; }; // Bundles a media::VideoCaptureDeviceDescriptor with corresponding supported @@ -199,6 +212,28 @@ media::VideoCaptureFormats supported_formats; }; +class BufferPoolFrameBufferPool : public media::FrameBufferPool { + public: + explicit BufferPoolFrameBufferPool( + scoped_refptr<media::VideoCaptureBufferPool> buffer_pool) + : buffer_pool_(std::move(buffer_pool)) {} + + void SetBufferHold(int buffer_id) override { + buffer_pool_->HoldForConsumers(buffer_id, 1); + } + + void ReleaseBufferHold(int buffer_id) override { + buffer_pool_->RelinquishConsumerHold(buffer_id, 1); + } + + mojo::ScopedSharedBufferHandle GetHandleForTransit(int buffer_id) override { + return buffer_pool_->GetHandleForTransit(buffer_id); + } + + private: + scoped_refptr<media::VideoCaptureBufferPool> buffer_pool_; +}; + // Class used for queuing request for starting a device. class VideoCaptureManager::CaptureDeviceStartRequest { public: @@ -226,44 +261,48 @@ VideoCaptureManager::DeviceEntry::DeviceEntry( MediaStreamType stream_type, const std::string& id, - std::unique_ptr<VideoCaptureController> controller, const media::VideoCaptureParams& params) : serial_id(g_device_start_id++), stream_type(stream_type), id(id), - parameters(params), - video_capture_controller_(std::move(controller)) {} + parameters(params) {} VideoCaptureManager::DeviceEntry::~DeviceEntry() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(BrowserThread::IO); // DCHECK that this DeviceEntry does not still own a // media::VideoCaptureDevice. media::VideoCaptureDevice must be deleted on // the device thread. - DCHECK(video_capture_device_ == nullptr); + DCHECK(video_capture_device == nullptr); } -void VideoCaptureManager::DeviceEntry::SetVideoCaptureDevice( - std::unique_ptr<VideoCaptureDevice> device) { - DCHECK(thread_checker_.CalledOnValidThread()); - video_capture_device_.swap(device); +std::unique_ptr<media::VideoCaptureDevice::Client> +VideoCaptureManager::DeviceEntry::CreateDeviceClient() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + const int max_buffers = stream_type == MEDIA_TAB_VIDEO_CAPTURE + ? kMaxNumberOfBuffersForTabCapture + : kMaxNumberOfBuffers; + if (!buffer_pool) { + buffer_pool = new media::VideoCaptureBufferPoolImpl( + base::MakeUnique<media::VideoCaptureBufferTrackerFactoryImpl>(), + max_buffers); + } + + return base::MakeUnique<media::VideoCaptureDeviceClient>( + base::MakeUnique<VideoFrameReceiverOnIOThread>( + video_capture_controller.GetWeakPtrForIOThread()), + buffer_pool, + base::Bind( + &CreateGpuJpegDecoder, + base::Bind(&media::VideoFrameReceiver::OnIncomingCapturedVideoFrame, + video_capture_controller.GetWeakPtrForIOThread()))); } -std::unique_ptr<media::VideoCaptureDevice> -VideoCaptureManager::DeviceEntry::ReleaseVideoCaptureDevice() { - DCHECK(thread_checker_.CalledOnValidThread()); - return std::move(video_capture_device_); -} - -VideoCaptureController* -VideoCaptureManager::DeviceEntry::video_capture_controller() const { - DCHECK(thread_checker_.CalledOnValidThread()); - return video_capture_controller_.get(); -} - -media::VideoCaptureDevice* -VideoCaptureManager::DeviceEntry::video_capture_device() const { - DCHECK(thread_checker_.CalledOnValidThread()); - return video_capture_device_.get(); +std::unique_ptr<media::FrameBufferPool> +VideoCaptureManager::DeviceEntry::CreateFrameBufferPool() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + DCHECK(buffer_pool); + return base::MakeUnique<BufferPoolFrameBufferPool>(buffer_pool); } VideoCaptureManager::DeviceInfo::DeviceInfo() = default; @@ -385,8 +424,7 @@ if (existing_device) { // Remove any client that is still using the session. This is safe to call // even if there are no clients using the session. - existing_device->video_capture_controller() - ->StopSession(capture_session_id); + existing_device->video_capture_controller.StopSession(capture_session_id); // StopSession() may have removed the last client, so we might need to // close the device. @@ -434,17 +472,18 @@ DVLOG(3) << "DoStopDevice. Send stop request for device = " << entry->id << " serial_id = " << entry->serial_id << "."; - entry->video_capture_controller()->OnLog( + entry->video_capture_controller.OnLog( base::StringPrintf("Stopping device: id: %s", entry->id.c_str())); - entry->video_capture_controller()->SetConsumerFeedbackObserver(nullptr); + entry->video_capture_controller.SetConsumerFeedbackObserver(nullptr); + entry->video_capture_controller.SetFrameBufferPool(nullptr); // |entry->video_capture_device| can be null if creating the device has // failed. - if (entry->video_capture_device()) { + if (entry->video_capture_device) { device_task_runner_->PostTask( FROM_HERE, base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, - base::Passed(entry->ReleaseVideoCaptureDevice()))); + base::Passed(&entry->video_capture_device))); } } @@ -466,6 +505,11 @@ DVLOG(3) << "HandleQueuedStartRequest, Post start to device thread, device = " << entry->id << " start id = " << entry->serial_id; + std::unique_ptr<media::VideoCaptureDevice::Client> device_client = + entry->CreateDeviceClient(); + std::unique_ptr<media::FrameBufferPool> frame_buffer_pool = + entry->CreateFrameBufferPool(); + base::Callback<std::unique_ptr<VideoCaptureDevice>(void)> start_capture_function; @@ -476,16 +520,16 @@ // held in the browser-side VideoCaptureDevice::Name structure. const DeviceInfo* found = GetDeviceInfoById(entry->id); if (found) { - entry->video_capture_controller()->OnLog( + entry->video_capture_controller.OnLog( base::StringPrintf("Starting device: id: %s, name: %s, api: %s", found->descriptor.device_id.c_str(), found->descriptor.GetNameAndModel().c_str(), found->descriptor.GetCaptureApiTypeString())); - start_capture_function = base::Bind( - &VideoCaptureManager::DoStartDeviceCaptureOnDeviceThread, this, - found->descriptor, request->params(), - base::Passed(entry->video_capture_controller()->NewDeviceClient())); + start_capture_function = + base::Bind(&VideoCaptureManager::DoStartDeviceCaptureOnDeviceThread, + this, found->descriptor, request->params(), + base::Passed(std::move(device_client))); } else { // Errors from DoStartDeviceCaptureOnDeviceThread go via // VideoCaptureDeviceClient::OnError, which needs some thread @@ -496,8 +540,8 @@ "Error on %s:%d: device %s unknown. Maybe recently disconnected?", __FILE__, __LINE__, entry->id.c_str()); DLOG(ERROR) << log_message; - entry->video_capture_controller()->OnLog(log_message); - entry->video_capture_controller()->OnError(); + entry->video_capture_controller.OnLog(log_message); + entry->video_capture_controller.OnError(); // Drop the failed start request. device_start_queue_.pop_front(); @@ -508,15 +552,13 @@ case MEDIA_TAB_VIDEO_CAPTURE: start_capture_function = base::Bind( &VideoCaptureManager::DoStartTabCaptureOnDeviceThread, this, - entry->id, request->params(), - base::Passed(entry->video_capture_controller()->NewDeviceClient())); + entry->id, request->params(), base::Passed(std::move(device_client))); break; case MEDIA_DESKTOP_VIDEO_CAPTURE: start_capture_function = base::Bind( &VideoCaptureManager::DoStartDesktopCaptureOnDeviceThread, this, - entry->id, request->params(), - base::Passed(entry->video_capture_controller()->NewDeviceClient())); + entry->id, request->params(), base::Passed(std::move(device_client))); break; default: { @@ -527,11 +569,12 @@ base::PostTaskAndReplyWithResult( device_task_runner_.get(), FROM_HERE, start_capture_function, base::Bind(&VideoCaptureManager::OnDeviceStarted, this, - request->serial_id())); + request->serial_id(), base::Passed(&frame_buffer_pool))); } void VideoCaptureManager::OnDeviceStarted( int serial_id, + std::unique_ptr<media::FrameBufferPool> frame_buffer_pool, std::unique_ptr<VideoCaptureDevice> device) { DVLOG(3) << __func__; DCHECK_CURRENTLY_ON(BrowserThread::IO); @@ -552,15 +595,19 @@ } else { DeviceEntry* const entry = GetDeviceEntryBySerialId(serial_id); DCHECK(entry); - DCHECK(!entry->video_capture_device()); - // Passing raw pointer |device.get()| to the controller is safe, - // because we transfer ownership of it to |entry|. We are calling - // SetConsumerFeedbackObserver(nullptr) before releasing - // |entry->video_capture_device_| on the |device_task_runner_|. - entry->video_capture_controller()->SetConsumerFeedbackObserver( - base::MakeUnique<VideoFrameConsumerFeedbackObserverOnTaskRunner>( - device.get(), device_task_runner_)); - entry->SetVideoCaptureDevice(std::move(device)); + DCHECK(!entry->video_capture_device); + if (device) { + entry->video_capture_controller.SetFrameBufferPool( + std::move(frame_buffer_pool)); + // Passing raw pointer |device.get()| to the controller is safe, + // because we transfer ownership of it to |entry|. We are calling + // SetConsumerFeedbackObserver(nullptr) before releasing + // |entry->video_capture_device_| on the |device_task_runner_|. + entry->video_capture_controller.SetConsumerFeedbackObserver( + base::MakeUnique<VideoFrameConsumerFeedbackObserverOnTaskRunner>( + device.get(), device_task_runner_)); + } + entry->video_capture_device = std::move(device); if (entry->stream_type == MEDIA_DESKTOP_VIDEO_CAPTURE) { const media::VideoCaptureSessionId session_id = @@ -573,8 +620,8 @@ while (it != photo_request_queue_.end()) { auto request = it++; DeviceEntry* maybe_entry = GetDeviceEntryBySessionId(request->first); - if (maybe_entry && maybe_entry->video_capture_device()) { - request->second.Run(maybe_entry->video_capture_device()); + if (maybe_entry && maybe_entry->video_capture_device) { + request->second.Run(maybe_entry->video_capture_device.get()); photo_request_queue_.erase(request); } } @@ -687,21 +734,19 @@ return; } - DCHECK(entry->video_capture_controller()); - LogVideoCaptureEvent(VIDEO_CAPTURE_START_CAPTURE); // First client starts the device. - if (!entry->video_capture_controller()->HasActiveClient() && - !entry->video_capture_controller()->HasPausedClient()) { + if (!entry->video_capture_controller.HasActiveClient() && + !entry->video_capture_controller.HasPausedClient()) { DVLOG(1) << "VideoCaptureManager starting device (type = " << entry->stream_type << ", id = " << entry->id << ")"; QueueStartDevice(session_id, entry, params); } // Run the callback first, as AddClient() may trigger OnFrameInfo(). - done_cb.Run(entry->video_capture_controller()->GetWeakPtrForIOThread()); - entry->video_capture_controller()->AddClient( - client_id, client_handler, session_id, params); + done_cb.Run(entry->video_capture_controller.GetWeakPtrForIOThread()); + entry->video_capture_controller.AddClient(client_id, client_handler, + session_id, params); } void VideoCaptureManager::StopCaptureForClient( @@ -766,7 +811,7 @@ controller->PauseClient(client_id, client_handler); if (!had_active_client || controller->HasActiveClient()) return; - if (media::VideoCaptureDevice* device = entry->video_capture_device()) { + if (media::VideoCaptureDevice* device = entry->video_capture_device.get()) { device_task_runner_->PostTask( FROM_HERE, base::Bind(&VideoCaptureDevice::MaybeSuspend, @@ -796,7 +841,7 @@ controller->ResumeClient(client_id, client_handler); if (had_active_client || !controller->HasActiveClient()) return; - if (media::VideoCaptureDevice* device = entry->video_capture_device()) { + if (media::VideoCaptureDevice* device = entry->video_capture_device.get()) { device_task_runner_->PostTask( FROM_HERE, base::Bind(&VideoCaptureDevice::Resume, @@ -813,7 +858,7 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); if (DeviceEntry* entry = GetDeviceEntryByController(controller)) { - if (media::VideoCaptureDevice* device = entry->video_capture_device()) { + if (media::VideoCaptureDevice* device = entry->video_capture_device.get()) { device_task_runner_->PostTask( FROM_HERE, base::Bind(&VideoCaptureDevice::RequestRefreshFrame, @@ -861,7 +906,7 @@ if (device_in_use) { // Currently only one format-in-use is supported at the VCC level. formats_in_use->push_back( - device_in_use->video_capture_controller()->GetVideoCaptureFormat()); + device_in_use->video_capture_controller.GetVideoCaptureFormat()); } return true; } @@ -889,7 +934,7 @@ return; } - if (!existing_device->video_capture_device()) { + if (!existing_device->video_capture_device) { DVLOG(2) << "Screen capture device not yet started."; return; } @@ -911,8 +956,7 @@ device_task_runner_->PostTask( FROM_HERE, base::Bind(&VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread, - this, - existing_device->video_capture_device(), + this, existing_device->video_capture_device.get(), window_id_it->second)); notification_window_ids_.erase(window_id_it); @@ -926,7 +970,7 @@ const DeviceEntry* entry = GetDeviceEntryBySessionId(session_id); if (!entry) return; - VideoCaptureDevice* device = entry->video_capture_device(); + VideoCaptureDevice* device = entry->video_capture_device.get(); if (device) { VideoCaptureManager::DoGetPhotoCapabilities(std::move(callback), device); return; @@ -946,7 +990,7 @@ const DeviceEntry* entry = GetDeviceEntryBySessionId(session_id); if (!entry) return; - VideoCaptureDevice* device = entry->video_capture_device(); + VideoCaptureDevice* device = entry->video_capture_device.get(); if (device) { VideoCaptureManager::DoSetPhotoOptions(std::move(callback), std::move(settings), device); @@ -966,7 +1010,7 @@ const DeviceEntry* entry = GetDeviceEntryBySessionId(session_id); if (!entry) return; - VideoCaptureDevice* device = entry->video_capture_device(); + VideoCaptureDevice* device = entry->video_capture_device.get(); if (device) { VideoCaptureManager::DoTakePhoto(std::move(callback), device); return; @@ -1074,8 +1118,8 @@ void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) { DCHECK_CURRENTLY_ON(BrowserThread::IO); // Removal of the last client stops the device. - if (!entry->video_capture_controller()->HasActiveClient() && - !entry->video_capture_controller()->HasPausedClient()) { + if (!entry->video_capture_controller.HasActiveClient() && + !entry->video_capture_controller.HasPausedClient()) { DVLOG(1) << "VideoCaptureManager stopping device (type = " << entry->stream_type << ", id = " << entry->id << ")"; @@ -1125,7 +1169,7 @@ // Look up |controller| in |devices_|. for (const std::unique_ptr<DeviceEntry>& device : devices_) { - if (device->video_capture_controller() == controller) + if (&device->video_capture_controller == controller) return device.get(); } return nullptr; @@ -1170,15 +1214,9 @@ return existing_device; } - const int max_buffers = device_info.type == MEDIA_TAB_VIDEO_CAPTURE ? - kMaxNumberOfBuffersForTabCapture : kMaxNumberOfBuffers; - std::unique_ptr<VideoCaptureController> video_capture_controller( - new VideoCaptureController(max_buffers)); - DeviceEntry* new_device = - new DeviceEntry(device_info.type, device_info.id, - std::move(video_capture_controller), params); - devices_.emplace_back(new_device); - return new_device; + devices_.emplace_back( + new DeviceEntry(device_info.type, device_info.id, params)); + return devices_.back().get(); } void VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread( @@ -1264,7 +1302,7 @@ // Do not resume Content Video Capture devices, e.g. Tab or Screen capture. // Do not try to restart already running devices. if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE || - entry->video_capture_device()) + entry->video_capture_device) continue; // Check if the device is already in the start queue.
diff --git a/content/browser/renderer_host/media/video_capture_manager.h b/content/browser/renderer_host/media/video_capture_manager.h index e6857c6..3bad7b1 100644 --- a/content/browser/renderer_host/media/video_capture_manager.h +++ b/content/browser/renderer_host/media/video_capture_manager.h
@@ -174,7 +174,7 @@ private: class CaptureDeviceStartRequest; - class DeviceEntry; + struct DeviceEntry; struct DeviceInfo; using SessionMap = std::map<media::VideoCaptureSessionId, MediaStreamDevice>; @@ -239,8 +239,10 @@ void QueueStartDevice(media::VideoCaptureSessionId session_id, DeviceEntry* entry, const media::VideoCaptureParams& params); - void OnDeviceStarted(int serial_id, - std::unique_ptr<VideoCaptureDevice> device); + void OnDeviceStarted( + int serial_id, + std::unique_ptr<media::FrameBufferPool> frame_buffer_pool, + std::unique_ptr<VideoCaptureDevice> device); void DoStopDevice(DeviceEntry* entry); void HandleQueuedStartRequest();
diff --git a/content/browser/renderer_host/media/video_frame_receiver_on_io_thread.cc b/content/browser/renderer_host/media/video_frame_receiver_on_io_thread.cc new file mode 100644 index 0000000..a4a46c2e --- /dev/null +++ b/content/browser/renderer_host/media/video_frame_receiver_on_io_thread.cc
@@ -0,0 +1,45 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/media/video_frame_receiver_on_io_thread.h" + +#include "content/public/browser/browser_thread.h" + +namespace content { + +VideoFrameReceiverOnIOThread::VideoFrameReceiverOnIOThread( + const base::WeakPtr<VideoFrameReceiver>& receiver) + : receiver_(receiver) {} + +VideoFrameReceiverOnIOThread::~VideoFrameReceiverOnIOThread() = default; + +void VideoFrameReceiverOnIOThread::OnIncomingCapturedVideoFrame( + std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer, + scoped_refptr<media::VideoFrame> frame) { + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::Bind(&VideoFrameReceiver::OnIncomingCapturedVideoFrame, receiver_, + base::Passed(&buffer), frame)); +} + +void VideoFrameReceiverOnIOThread::OnError() { + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::Bind(&VideoFrameReceiver::OnError, receiver_)); +} + +void VideoFrameReceiverOnIOThread::OnLog(const std::string& message) { + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::Bind(&VideoFrameReceiver::OnLog, receiver_, message)); +} + +void VideoFrameReceiverOnIOThread::OnBufferDestroyed(int buffer_id_to_drop) { + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::Bind(&VideoFrameReceiver::OnBufferDestroyed, receiver_, + buffer_id_to_drop)); +} + +} // namespace content
diff --git a/content/browser/renderer_host/media/video_frame_receiver_on_io_thread.h b/content/browser/renderer_host/media/video_frame_receiver_on_io_thread.h new file mode 100644 index 0000000..9925dd1 --- /dev/null +++ b/content/browser/renderer_host/media/video_frame_receiver_on_io_thread.h
@@ -0,0 +1,37 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_FRAME_RECEIVER_ON_IO_THREAD_H_ +#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_FRAME_RECEIVER_ON_IO_THREAD_H_ + +#include "content/common/content_export.h" +#include "media/capture/video/video_frame_receiver.h" + +namespace content { + +// Decorator for media::VideoFrameReceiver that forwards all incoming calls +// to the Browser IO thread. +// TODO(chfremer): Change this to VideoFrameReceiverOnTaskRunner and have the +// target task runner be passed into the constructor. See crbug.com/674190. +class CONTENT_EXPORT VideoFrameReceiverOnIOThread + : public media::VideoFrameReceiver { + public: + explicit VideoFrameReceiverOnIOThread( + const base::WeakPtr<VideoFrameReceiver>& receiver); + ~VideoFrameReceiverOnIOThread() override; + + void OnIncomingCapturedVideoFrame( + std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer, + scoped_refptr<media::VideoFrame> frame) override; + void OnError() override; + void OnLog(const std::string& message) override; + void OnBufferDestroyed(int buffer_id_to_drop) override; + + private: + base::WeakPtr<VideoFrameReceiver> receiver_; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_FRAME_RECEIVER_ON_IO_THREAD_H_
diff --git a/content/browser/renderer_host/render_widget_host_delegate.cc b/content/browser/renderer_host/render_widget_host_delegate.cc index 606370d..d2740e3b 100644 --- a/content/browser/renderer_host/render_widget_host_delegate.cc +++ b/content/browser/renderer_host/render_widget_host_delegate.cc
@@ -99,4 +99,8 @@ return false; } +WebContents* RenderWidgetHostDelegate::GetAsWebContents() { + return nullptr; +} + } // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_delegate.h b/content/browser/renderer_host/render_widget_host_delegate.h index 68346580..8030e15 100644 --- a/content/browser/renderer_host/render_widget_host_delegate.h +++ b/content/browser/renderer_host/render_widget_host_delegate.h
@@ -40,6 +40,7 @@ class RenderWidgetHostInputEventRouter; class RenderViewHostDelegateView; class TextInputManager; +class WebContents; struct ScreenInfo; struct NativeWebKeyboardEvent; @@ -249,6 +250,10 @@ // element accepts text input. virtual void FocusedNodeTouched(bool editable) {} + // Return this object cast to a WebContents, if it is one. If the object is + // not a WebContents, returns nullptr. + virtual WebContents* GetAsWebContents(); + protected: virtual ~RenderWidgetHostDelegate() {} };
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 37e88877..a1542f0 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1923,12 +1923,16 @@ bool user_gesture, bool last_unlocked_by_target, bool privileged) { - if (mouse_lock_widget_) { - render_widget_host->GotResponseToLockMouseRequest(false); - return; + for (WebContentsImpl* current = this; current; + current = current->GetOuterWebContents()) { + if (current->mouse_lock_widget_) { + render_widget_host->GotResponseToLockMouseRequest(false); + return; + } } if (privileged) { + DCHECK(!GetOuterWebContents()); mouse_lock_widget_ = render_widget_host; render_widget_host->GotResponseToLockMouseRequest(true); return; @@ -1944,7 +1948,11 @@ } if (widget_in_frame_tree && delegate_) { - mouse_lock_widget_ = render_widget_host; + for (WebContentsImpl* current = this; current; + current = current->GetOuterWebContents()) { + current->mouse_lock_widget_ = render_widget_host; + } + delegate_->RequestToLockMouse(this, user_gesture, last_unlocked_by_target); } else { render_widget_host->GotResponseToLockMouseRequest(false); @@ -1953,8 +1961,15 @@ void WebContentsImpl::LostMouseLock(RenderWidgetHostImpl* render_widget_host) { CHECK(mouse_lock_widget_); + + if (mouse_lock_widget_->delegate()->GetAsWebContents() != this) + return mouse_lock_widget_->delegate()->LostMouseLock(render_widget_host); + mouse_lock_widget_->SendMouseLockLost(); - mouse_lock_widget_ = nullptr; + for (WebContentsImpl* current = this; current; + current = current->GetOuterWebContents()) { + current->mouse_lock_widget_ = nullptr; + } if (delegate_) delegate_->LostMouseLock(); @@ -3070,14 +3085,26 @@ } bool WebContentsImpl::GotResponseToLockMouseRequest(bool allowed) { - if (GetBrowserPluginGuest()) + if (!GuestMode::IsCrossProcessFrameGuest(GetWebContents()) && + GetBrowserPluginGuest()) return GetBrowserPluginGuest()->LockMouse(allowed); - if (mouse_lock_widget_ && - mouse_lock_widget_->GotResponseToLockMouseRequest(allowed)) - return true; + if (mouse_lock_widget_) { + if (mouse_lock_widget_->delegate()->GetAsWebContents() != this) { + return mouse_lock_widget_->delegate() + ->GetAsWebContents() + ->GotResponseToLockMouseRequest(allowed); + } - mouse_lock_widget_ = nullptr; + if (mouse_lock_widget_->GotResponseToLockMouseRequest(allowed)) + return true; + } + + for (WebContentsImpl* current = this; current; + current = current->GetOuterWebContents()) { + current->mouse_lock_widget_ = nullptr; + } + return false; }
diff --git a/content/browser/webui/i18n_source_stream.cc b/content/browser/webui/i18n_source_stream.cc index 1ff237e2..c2120a8 100644 --- a/content/browser/webui/i18n_source_stream.cc +++ b/content/browser/webui/i18n_source_stream.cc
@@ -29,7 +29,6 @@ SourceStream::SourceType type, const ui::TemplateReplacements* replacements) : FilterSourceStream(type, std::move(upstream)), - drain_offset_(0), replacements_(replacements) {} std::string I18nSourceStream::GetTypeAsString() const { @@ -42,24 +41,30 @@ int input_buffer_size, int* consumed_bytes, bool upstream_end_reached) { - DCHECK(output_.empty() || (upstream_end_reached && input_buffer_size == 0)); - *consumed_bytes = input_buffer_size; - // TODO(dschuyler): Perform replacements without accumulation. - // Accumulate. + // |input_| is often empty (or it may have something from the prior call). input_.append(input_buffer->data(), input_buffer_size); - if (upstream_end_reached && !drain_offset_ && output_.empty()) { - // Process. - output_ = ui::ReplaceTemplateExpressions(input_, *replacements_); + *consumed_bytes = input_buffer_size; + + // The replacement tag starts with '$' and ends with '}'. The white-space + // characters are an optimization that looks for characters that are invalid + // within $i18n{} tags. + size_t pos = input_.find_last_of("$} \t\r\n"); + std::string to_process; + if (!upstream_end_reached && pos != std::string::npos && input_[pos] == '$') { + // If there is a trailing '$' then split the |input_| at that point. Process + // the first part; save the second part for the next call to FilterData(). + to_process.assign(input_, 0, pos); + input_.erase(0, pos); + } else { + // There is no risk of a split key, process the whole input. + to_process.swap(input_); } - if (drain_offset_ == output_.size()) - return 0; - - // Drain. - int bytes_out = std::min(output_.size() - drain_offset_, - static_cast<size_t>(output_buffer_size)); - output_.copy(output_buffer->data(), bytes_out, drain_offset_); - drain_offset_ += bytes_out; + output_.append(ui::ReplaceTemplateExpressions(to_process, *replacements_)); + int bytes_out = + std::min(output_.size(), static_cast<size_t>(output_buffer_size)); + output_.copy(output_buffer->data(), bytes_out); + output_.erase(0, bytes_out); return bytes_out; }
diff --git a/content/browser/webui/i18n_source_stream.h b/content/browser/webui/i18n_source_stream.h index 0f37d87..64378c8 100644 --- a/content/browser/webui/i18n_source_stream.h +++ b/content/browser/webui/i18n_source_stream.h
@@ -40,15 +40,16 @@ int* consumed_bytes, bool upstream_end_reached) override; - // Accumulated from upstream. + // Keep split $i18n tags (wait for the whole tag). This is expected to vary + // in size from 0 to a few KB and should never be larger than the input file + // (in the worst case). std::string input_; - // To send downstream. + // Keep excess that didn't fit in the output buffer. This is expected to vary + // in size from 0 to a few KB and should never get much larger than the input + // file (in the worst case). std::string output_; - // How much of the |output_| has been sent. - size_t drain_offset_; - // A map of i18n replacement keys and translations. const ui::TemplateReplacements* replacements_; // weak
diff --git a/content/browser/webui/i18n_source_stream_unittest.cc b/content/browser/webui/i18n_source_stream_unittest.cc index 76ebf69..d031240 100644 --- a/content/browser/webui/i18n_source_stream_unittest.cc +++ b/content/browser/webui/i18n_source_stream_unittest.cc
@@ -178,19 +178,18 @@ const char kText[] = "This text has no i18n replacements."; size_t kTextLength = strlen(kText); source()->AddReadResult(kText, kTextLength, net::OK, GetParam().mode); - source()->AddReadResult(kText + kTextLength, 0, net::OK, GetParam().mode); + source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode); std::string actual_output; int rv = ReadStream(&actual_output); EXPECT_EQ(static_cast<int>(kTextLength), rv); - EXPECT_EQ(std::string(kText, kTextLength), actual_output); + EXPECT_EQ(kText, actual_output); EXPECT_EQ("i18n", stream()->Description()); } TEST_P(I18nSourceStreamTest, I18nOneRead) { Init(); source()->AddReadResult(source_data(), kSourceSize, net::OK, GetParam().mode); - source()->AddReadResult(source_data() + kSourceSize, 0, net::OK, - GetParam().mode); + source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode); std::string actual_output; int rv = ReadStream(&actual_output); EXPECT_EQ(static_cast<int>(kResultSize), rv); @@ -209,8 +208,7 @@ } source()->AddReadResult(source_data() + written, kSourceSize - written, net::OK, GetParam().mode); - source()->AddReadResult(source_data() + kSourceSize, 0, net::OK, - GetParam().mode); + source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode); std::string actual_output; int rv = ReadStream(&actual_output); EXPECT_EQ(static_cast<int>(kResultSize), rv); @@ -218,4 +216,17 @@ EXPECT_EQ("i18n", stream()->Description()); } +TEST_P(I18nSourceStreamTest, I18nTagAtEndOfLine) { + Init(); + const char kSourceData[] = "test with tag at end of line $"; + const size_t source_size = strlen(kSourceData); + source()->AddReadResult(kSourceData, source_size, net::OK, GetParam().mode); + source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode); + std::string actual_output; + int rv = ReadStream(&actual_output); + EXPECT_EQ(static_cast<int>(source_size), rv); + EXPECT_EQ(kSourceData, actual_output); + EXPECT_EQ("i18n", stream()->Description()); +} + } // namespace content
diff --git a/content/common/video_capture.mojom b/content/common/video_capture.mojom index 358fb4ad98..bfa1ee2 100644 --- a/content/common/video_capture.mojom +++ b/content/common/video_capture.mojom
@@ -4,7 +4,6 @@ module content.mojom; -import "gpu/ipc/common/sync_token.mojom"; import "media/mojo/interfaces/media_types.mojom"; import "media/capture/mojo/video_capture_types.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom"; @@ -98,7 +97,6 @@ // Indicates that a renderer has finished using a previously shared buffer. ReleaseBuffer(int32 device_id, int32 buffer_id, - gpu.mojom.SyncToken sync_token, double consumer_resource_utilization); // Get the formats supported by a device referenced by |session_id|.
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java index 994b458a..6d63ded 100644 --- a/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java +++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java
@@ -37,9 +37,6 @@ public class BrowserAccessibilityManager { private static final String TAG = "BrowserAccessibilityManager"; - private static final int WINDOW_CONTENT_CHANGED_DELAY_MS = 500; - private static final int ACCESSIBILITY_FOCUS_LOCATION_CHANGED_DELAY_MS = 100; - // Constants from AccessibilityNodeInfo defined in the K SDK. private static final int ACTION_COLLAPSE = 0x00080000; private static final int ACTION_EXPAND = 0x00040000; @@ -48,6 +45,7 @@ private static final int ACTION_SET_TEXT = 0x200000; private static final String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE = "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE"; + private static final int WINDOW_CONTENT_CHANGED_DELAY_MS = 500; // Constants from AccessibilityNodeInfo defined in the M SDK. // Source: https://developer.android.com/reference/android/R.id.html @@ -77,7 +75,6 @@ private int mSelectionEndIndex; protected int mAccessibilityFocusId; private Runnable mSendWindowContentChangedRunnable; - private Runnable mAccessibilityFocusLocationChangedRunnable; /** * Create a BrowserAccessibilityManager object, which is owned by the C++ @@ -240,12 +237,6 @@ if (mAccessibilityFocusId == virtualViewId) { mAccessibilityFocusId = View.NO_ID; mAccessibilityFocusRect = null; - // If we had a pending callback to update the location of the previous object - // with accessibility focus, remove it. - if (mAccessibilityFocusLocationChangedRunnable != null) { - mView.removeCallbacks(mAccessibilityFocusLocationChangedRunnable); - mAccessibilityFocusLocationChangedRunnable = null; - } } return true; case AccessibilityNodeInfo.ACTION_CLICK: @@ -546,20 +537,6 @@ mSelectionStartIndex = 0; mSelectionEndIndex = 0; - // If we had a pending callback to update the location of the previous object with - // accessibility focus, remove it. - if (mAccessibilityFocusLocationChangedRunnable != null) { - mView.removeCallbacks(mAccessibilityFocusLocationChangedRunnable); - mAccessibilityFocusLocationChangedRunnable = null; - } - - // Call nativeSetAccessibilityFocus. For the most part Chrome doesn't have a - // concept of accessibility focus, but we do two things: (1) auto-focus certain - // roles like links when they get accessibility focus and (2) load inline text boxes - // for nodes when they get accessibility focus since inline text boxes are expensive - // to load and on Android they're only needed for nodes that have input focus or - // accessibility focus. - // // Calling nativeSetAccessibilityFocus will asynchronously load inline text boxes for // this node and its subtree. If accessibility focus is on anything other than // the root, do it - otherwise set it to -1 so we don't load inline text boxes @@ -589,47 +566,6 @@ } /** - * Work around a bug in the Android framework where if the object with accessibility - * focus moves, the accessibility focus rect is not updated - both the visual highlight, - * and the location on the screen that's clicked if you double-tap. To work around this, - * when we know the object with accessibility focus moved, move focus away and then - * move focus right back to it, which tricks Android into updating its bounds. - * - * Do this after a short delay because sometimes the change to the object with accessibility - * focus happens just before navigating somewhere else. - */ - private void updateAccessibilityFocusLocationAfterDelay() { - if (mNativeObj == 0) return; - - if (mAccessibilityFocusLocationChangedRunnable != null) return; - - mAccessibilityFocusLocationChangedRunnable = new Runnable() { - @Override - public void run() { - updateAccessibilityFocusLocation(); - } - }; - - mView.postDelayed(mAccessibilityFocusLocationChangedRunnable, - ACCESSIBILITY_FOCUS_LOCATION_CHANGED_DELAY_MS); - } - - /** - * See updateAccessibilityFocusLocationAfterDelay for details. - */ - private void updateAccessibilityFocusLocation() { - // This can be called from a timeout, so we need to make sure we're still valid. - if (mNativeObj == 0 || mContentViewCore == null || mView == null) return; - - if (mAccessibilityFocusLocationChangedRunnable != null) { - mView.removeCallbacks(mAccessibilityFocusLocationChangedRunnable); - mAccessibilityFocusLocationChangedRunnable = null; - } - - moveAccessibilityFocusToIdAndRefocusIfNeeded(mAccessibilityFocusId); - } - - /** * Send a WINDOW_CONTENT_CHANGED event after a short delay. This helps throttle such * events from firing too quickly during animations, for example. */ @@ -1056,14 +992,17 @@ node.setBoundsInScreen(rect); - // If this is the node with accessibility focus, ensure that its location on-screen - // is up-to-date. + // Work around a bug in the Android framework where if the object with accessibility + // focus moves, the accessibility focus rect is not updated - both the visual highlight, + // and the location on the screen that's clicked if you double-tap. To work around this, + // when we know the object with accessibility focus moved, move focus away and then + // move focus right back to it, which tricks Android into updating its bounds. if (virtualViewId == mAccessibilityFocusId && virtualViewId != mCurrentRootId) { if (mAccessibilityFocusRect == null) { mAccessibilityFocusRect = rect; } else if (!mAccessibilityFocusRect.equals(rect)) { mAccessibilityFocusRect = rect; - updateAccessibilityFocusLocationAfterDelay(); + moveAccessibilityFocusToIdAndRefocusIfNeeded(virtualViewId); } } }
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/FloatingPastePopupMenu.java b/content/public/android/java/src/org/chromium/content/browser/input/FloatingPastePopupMenu.java index c5310db4..2864cf76 100644 --- a/content/public/android/java/src/org/chromium/content/browser/input/FloatingPastePopupMenu.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/FloatingPastePopupMenu.java
@@ -43,10 +43,6 @@ private int mRawPositionX; private int mRawPositionY; - // Embedders may not support floating ActionModes, in which case we should - // use the legacy menu as a fallback. - private LegacyPastePopupMenu mFallbackPastePopupMenu; - public FloatingPastePopupMenu(Context context, View parent, PastePopupMenuDelegate delegate) { assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; @@ -63,11 +59,6 @@ @Override public void show(int x, int y) { - if (mFallbackPastePopupMenu != null) { - mFallbackPastePopupMenu.show(x, y); - return; - } - if (isShowing()) { int dx = mRawPositionX - x; int dy = mRawPositionY - y; @@ -81,16 +72,11 @@ return; } - ensureActionModeOrFallback(); + ensureActionMode(); } @Override public void hide() { - if (mFallbackPastePopupMenu != null) { - mFallbackPastePopupMenu.hide(); - return; - } - if (mActionMode != null) { mActionMode.finish(); mActionMode = null; @@ -99,13 +85,11 @@ @Override public boolean isShowing() { - if (mFallbackPastePopupMenu != null) return mFallbackPastePopupMenu.isShowing(); return mActionMode != null; } - private void ensureActionModeOrFallback() { + private void ensureActionMode() { if (mActionMode != null) return; - if (mFallbackPastePopupMenu != null) return; ActionMode actionMode = mParent.startActionMode( new ActionModeCallback(), ActionMode.TYPE_FLOATING); @@ -115,9 +99,6 @@ assert actionMode.getType() == ActionMode.TYPE_FLOATING; mActionMode = actionMode; - } else { - mFallbackPastePopupMenu = new LegacyPastePopupMenu(mContext, mParent, mDelegate); - mFallbackPastePopupMenu.show(mRawPositionX, mRawPositionY); } }
diff --git a/content/renderer/media/video_capture_impl.cc b/content/renderer/media/video_capture_impl.cc index b46d35a..089fcbc 100644 --- a/content/renderer/media/video_capture_impl.cc +++ b/content/renderer/media/video_capture_impl.cc
@@ -269,8 +269,7 @@ << ", storage:" << info->storage_type; } if (!consume_buffer) { - GetVideoCaptureHost()->ReleaseBuffer(device_id_, buffer_id, - gpu::SyncToken(), -1.0); + GetVideoCaptureHost()->ReleaseBuffer(device_id_, buffer_id, -1.0); return; } @@ -310,18 +309,16 @@ buffer->buffer_size(), buffer->buffer()->handle(), 0 /* shared_memory_offset */, info->timestamp); if (!frame) { - GetVideoCaptureHost()->ReleaseBuffer(device_id_, buffer_id, - gpu::SyncToken(), -1.0); + GetVideoCaptureHost()->ReleaseBuffer(device_id_, buffer_id, -1.0); return; } BufferFinishedCallback buffer_finished_callback = media::BindToCurrentLoop( base::Bind(&VideoCaptureImpl::OnClientBufferFinished, weak_factory_.GetWeakPtr(), buffer_id, buffer)); - std::unique_ptr<gpu::SyncToken> release_sync_token(new gpu::SyncToken); frame->AddDestructionObserver( base::Bind(&VideoCaptureImpl::DidFinishConsumingFrame, frame->metadata(), - base::Passed(&release_sync_token), buffer_finished_callback)); + buffer_finished_callback)); frame->metadata()->MergeInternalValuesFrom(*info->metadata); @@ -345,11 +342,10 @@ void VideoCaptureImpl::OnClientBufferFinished( int buffer_id, const scoped_refptr<ClientBuffer>& /* ignored_buffer */, - const gpu::SyncToken& release_sync_token, double consumer_resource_utilization) { DCHECK(io_thread_checker_.CalledOnValidThread()); GetVideoCaptureHost()->ReleaseBuffer( - device_id_, buffer_id, release_sync_token, consumer_resource_utilization); + device_id_, buffer_id, consumer_resource_utilization); } void VideoCaptureImpl::StopDevice() { @@ -428,7 +424,6 @@ // static void VideoCaptureImpl::DidFinishConsumingFrame( const media::VideoFrameMetadata* metadata, - std::unique_ptr<gpu::SyncToken> release_sync_token, const BufferFinishedCallback& callback_to_io_thread) { // Note: This function may be called on any thread by the VideoFrame // destructor. |metadata| is still valid for read-access at this point. @@ -437,8 +432,7 @@ &consumer_resource_utilization)) { consumer_resource_utilization = -1.0; } - - callback_to_io_thread.Run(*release_sync_token, consumer_resource_utilization); + callback_to_io_thread.Run(consumer_resource_utilization); } } // namespace content
diff --git a/content/renderer/media/video_capture_impl.h b/content/renderer/media/video_capture_impl.h index f875e71..b39b999 100644 --- a/content/renderer/media/video_capture_impl.h +++ b/content/renderer/media/video_capture_impl.h
@@ -80,8 +80,7 @@ using ClientInfoMap = std::map<int, ClientInfo>; using BufferFinishedCallback = - base::Callback<void(const gpu::SyncToken& sync_token, - double consumer_resource_utilization)>; + base::Callback<void(double consumer_resource_utilization)>; // mojom::VideoCaptureObserver implementation. void OnStateChanged(mojom::VideoCaptureState state) override; @@ -95,7 +94,6 @@ // buffer. void OnClientBufferFinished(int buffer_id, const scoped_refptr<ClientBuffer>& buffer, - const gpu::SyncToken& release_sync_token, double consumer_resource_utilization); void StopDevice(); @@ -120,7 +118,6 @@ // callback, to trampoline back to the IO thread with the values. static void DidFinishConsumingFrame( const media::VideoFrameMetadata* metadata, - std::unique_ptr<gpu::SyncToken> release_sync_token, const BufferFinishedCallback& callback_to_io_thread); // |device_id_| and |session_id_| are different concepts, but we reuse the
diff --git a/content/renderer/media/video_capture_impl_manager_unittest.cc b/content/renderer/media/video_capture_impl_manager_unittest.cc index d1af016..a68a26b 100644 --- a/content/renderer/media/video_capture_impl_manager_unittest.cc +++ b/content/renderer/media/video_capture_impl_manager_unittest.cc
@@ -76,8 +76,8 @@ } MOCK_METHOD1(RequestRefreshFrame, void(int32_t)); - MOCK_METHOD4(ReleaseBuffer, - void(int32_t, int32_t, const gpu::SyncToken&, double)); + MOCK_METHOD3(ReleaseBuffer, + void(int32_t, int32_t, double)); MOCK_METHOD3(GetDeviceSupportedFormats, void(int32_t, int32_t,
diff --git a/content/renderer/media/video_capture_impl_unittest.cc b/content/renderer/media/video_capture_impl_unittest.cc index 9fee656c..f130682 100644 --- a/content/renderer/media/video_capture_impl_unittest.cc +++ b/content/renderer/media/video_capture_impl_unittest.cc
@@ -37,7 +37,7 @@ .WillByDefault(WithArgs<2>(Invoke(RunEmptyFormatsCallback))); ON_CALL(*this, GetDeviceFormatsInUse(_, _, _)) .WillByDefault(WithArgs<2>(Invoke(RunEmptyFormatsCallback))); - ON_CALL(*this, ReleaseBuffer(_, _, _, _)) + ON_CALL(*this, ReleaseBuffer(_, _, _)) .WillByDefault(InvokeWithoutArgs( this, &MockMojoVideoCaptureHost::increase_released_buffer_count)); } @@ -56,8 +56,7 @@ MOCK_METHOD3(Resume, void(int32_t, int32_t, const media::VideoCaptureParams&)); MOCK_METHOD1(RequestRefreshFrame, void(int32_t)); - MOCK_METHOD4(ReleaseBuffer, - void(int32_t, int32_t, const gpu::SyncToken&, double)); + MOCK_METHOD3(ReleaseBuffer, void(int32_t, int32_t, double)); MOCK_METHOD3(GetDeviceSupportedFormats, void(int32_t, int32_t, @@ -265,7 +264,7 @@ EXPECT_CALL(*this, OnFrameReady(_, _)); EXPECT_CALL(mock_video_capture_host_, DoStart(_, kSessionId, params_small_)); EXPECT_CALL(mock_video_capture_host_, Stop(_)); - EXPECT_CALL(mock_video_capture_host_, ReleaseBuffer(_, kBufferId, _, _)) + EXPECT_CALL(mock_video_capture_host_, ReleaseBuffer(_, kBufferId, _)) .Times(0); StartCapture(0, params_small_); @@ -290,7 +289,7 @@ EXPECT_CALL(*this, OnFrameReady(_, _)).Times(0); EXPECT_CALL(mock_video_capture_host_, DoStart(_, kSessionId, params_large_)); EXPECT_CALL(mock_video_capture_host_, Stop(_)); - EXPECT_CALL(mock_video_capture_host_, ReleaseBuffer(_, kBufferId, _, _)); + EXPECT_CALL(mock_video_capture_host_, ReleaseBuffer(_, kBufferId, _)); StartCapture(0, params_large_); SimulateOnBufferCreated(kBufferId, shm);
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index 4df0363..c90e9c3 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -55,6 +55,7 @@ # Windows only. self.Fail('conformance2/rendering/blitframebuffer-outside-readbuffer.html', ['win'], bug=644740) + self.Flaky('deqp/functional/gles3/sync.html', ['win'], bug=676848) # Win / NVidia self.Flaky('deqp/functional/gles3/fbomultisample*',
diff --git a/crypto/capi_util.cc b/crypto/capi_util.cc index 7adfeb8..1e199db 100644 --- a/crypto/capi_util.cc +++ b/crypto/capi_util.cc
@@ -5,49 +5,10 @@ #include "crypto/capi_util.h" #include <stddef.h> - -#include "base/macros.h" -#include "base/memory/singleton.h" -#include "base/synchronization/lock.h" - -namespace { - -class CAPIUtilSingleton { - public: - static CAPIUtilSingleton* GetInstance() { - return base::Singleton<CAPIUtilSingleton>::get(); - } - - // Returns a lock to guard calls to CryptAcquireContext with - // CRYPT_DELETEKEYSET or CRYPT_NEWKEYSET. - base::Lock& acquire_context_lock() { - return acquire_context_lock_; - } - - private: - friend class base::Singleton<CAPIUtilSingleton>; - friend struct base::DefaultSingletonTraits<CAPIUtilSingleton>; - - CAPIUtilSingleton() {} - - base::Lock acquire_context_lock_; - - DISALLOW_COPY_AND_ASSIGN(CAPIUtilSingleton); -}; - -} // namespace +#include <stdlib.h> namespace crypto { -BOOL CryptAcquireContextLocked(HCRYPTPROV* prov, - LPCWSTR container, - LPCWSTR provider, - DWORD prov_type, - DWORD flags) { - base::AutoLock lock(CAPIUtilSingleton::GetInstance()->acquire_context_lock()); - return CryptAcquireContext(prov, container, provider, prov_type, flags); -} - void* WINAPI CryptAlloc(size_t size) { return malloc(size); }
diff --git a/crypto/capi_util.h b/crypto/capi_util.h index 6941033..11e2b7b 100644 --- a/crypto/capi_util.h +++ b/crypto/capi_util.h
@@ -9,26 +9,9 @@ #include <stddef.h> #include "crypto/crypto_export.h" -#include "crypto/wincrypt_shim.h" namespace crypto { -// CryptAcquireContext when passed CRYPT_NEWKEYSET or CRYPT_DELETEKEYSET in -// flags is not thread-safe. For such calls, we create a global lock to -// synchronize it. -// -// From "Threading Issues with Cryptographic Service Providers", -// <http://msdn.microsoft.com/en-us/library/aa388149(v=VS.85).aspx>: -// -// "The CryptAcquireContext function is generally thread safe unless -// CRYPT_NEWKEYSET or CRYPT_DELETEKEYSET is specified in the dwFlags -// parameter." -CRYPTO_EXPORT BOOL CryptAcquireContextLocked(HCRYPTPROV* prov, - LPCWSTR container, - LPCWSTR provider, - DWORD prov_type, - DWORD flags); - // Wrappers of malloc and free for CryptoAPI routines that need memory // allocators, such as in CRYPT_DECODE_PARA. Such routines require WINAPI // calling conventions.
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc index 4276b3c9..47f4a6ee 100644 --- a/extensions/browser/guest_view/web_view/web_view_guest.cc +++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -1375,6 +1375,16 @@ return is_guest_fullscreen_; } +void WebViewGuest::RequestToLockMouse(WebContents* web_contents, + bool user_gesture, + bool last_unlocked_by_target) { + RequestPointerLockPermission( + user_gesture, last_unlocked_by_target, + base::Bind( + base::IgnoreResult(&WebContents::GotResponseToLockMouseRequest), + base::Unretained(web_contents))); +} + void WebViewGuest::LoadURLWithParams( const GURL& url, const content::Referrer& referrer,
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.h b/extensions/browser/guest_view/web_view/web_view_guest.h index 79db5bf2..2a3befd5 100644 --- a/extensions/browser/guest_view/web_view/web_view_guest.h +++ b/extensions/browser/guest_view/web_view/web_view_guest.h
@@ -253,6 +253,9 @@ void ExitFullscreenModeForTab(content::WebContents* web_contents) final; bool IsFullscreenForTabOrPending( const content::WebContents* web_contents) const final; + void RequestToLockMouse(content::WebContents* web_contents, + bool user_gesture, + bool last_unlocked_by_target) override; // WebContentsObserver implementation. void DidStartNavigation(content::NavigationHandle* navigation_handle) final;
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc index 56d598fc..6b93df46 100644 --- a/gpu/config/gpu_driver_bug_list_json.cc +++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -200,9 +200,9 @@ { "id": 31, "cr_bugs": [154715, 10068, 269829, 294779, 285292], - "description": "The Mali-xxx driver does not guarantee flush ordering", + "description": "The Mali-Txxx driver does not guarantee flush ordering", "gl_vendor": "ARM.*", - "gl_renderer": "Mali.*", + "gl_renderer": "Mali-T.*", "features": [ "use_virtualized_gl_contexts" ]
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index e565127..352e988 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -400,6 +400,8 @@ - (void)showSyncSettings; // Shows the Save Passwords settings. - (void)showSavePasswordsSettings; +// Shows the Physical Web settings UI. +- (void)showPhysicalWebSettings; // Invokes the sign in flow with the specified authentication operation and // invokes |callback| when finished. - (void)showSignInWithOperation:(AuthenticationOperation)operation @@ -1525,6 +1527,9 @@ case IDC_SHOW_SAVE_PASSWORDS_SETTINGS: [self showSavePasswordsSettings]; break; + case IDC_SHOW_PHYSICAL_WEB_SETTINGS: + [self showPhysicalWebSettings]; + break; case IDC_SHOW_HISTORY: [self showHistory]; break; @@ -2111,6 +2116,18 @@ completion:nil]; } +- (void)showPhysicalWebSettings { + if (_settingsNavigationController) + return; + _settingsNavigationController.reset([SettingsNavigationController + newPhysicalWebController:_mainBrowserState + delegate:self]); + [[self topPresentedViewController] + presentViewController:_settingsNavigationController + animated:YES + completion:nil]; +} + - (void)showReportAnIssue { if (_settingsNavigationController) return;
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_popup_material_row.h b/ios/chrome/browser/ui/omnibox/omnibox_popup_material_row.h index 334b758..4a2da9834 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_popup_material_row.h +++ b/ios/chrome/browser/ui/omnibox/omnibox_popup_material_row.h
@@ -21,7 +21,7 @@ @property(nonatomic, readonly, retain) UIImageView* imageView; @property(nonatomic, readonly, retain) UIImageView* answerImageView; @property(nonatomic, readonly, retain) UIButton* appendButton; -@property(nonatomic, readonly, retain) UIImageView* physicalWebImageView; +@property(nonatomic, readonly, retain) UIButton* physicalWebButton; @property(nonatomic, assign) CGFloat rowHeight; // Initialize the row with the given incognito state. The colors and styling are
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_popup_material_row.mm b/ios/chrome/browser/ui/omnibox/omnibox_popup_material_row.mm index be53f8a6..e105675 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_popup_material_row.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_popup_material_row.mm
@@ -34,9 +34,9 @@ @synthesize textTruncatingLabel = _textTruncatingLabel; @synthesize detailTruncatingLabel = _detailTruncatingLabel; @synthesize appendButton = _appendButton; +@synthesize physicalWebButton = _physicalWebButton; @synthesize answerImageView = _answerImageView; @synthesize imageView = _imageView; -@synthesize physicalWebImageView = _physicalWebImageView; @synthesize rowHeight = _rowHeight; - (instancetype)initWithStyle:(UITableViewCellStyle)style @@ -73,11 +73,10 @@ // The current implementation is from before using a UITableViewCell. [self addSubview:_appendButton]; - _physicalWebImageView = [[UIImageView alloc] initWithFrame:CGRectZero]; - _physicalWebImageView.userInteractionEnabled = NO; - _physicalWebImageView.contentMode = UIViewContentModeCenter; - _physicalWebImageView.image = NativeImage(IDR_IOS_OMNIBOX_PHYSICAL_WEB); - [self addSubview:_physicalWebImageView]; + _physicalWebButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain]; + [_physicalWebButton setContentMode:UIViewContentModeRight]; + [self updatePhysicalWebImage]; + [self addSubview:_physicalWebButton]; // Left icon is only displayed on iPad. if (IsIPadIdiom()) { @@ -120,7 +119,7 @@ floor((_rowHeight - appendButtonDimensionLength) / 2), appendButtonDimensionLength, appendButtonDimensionLength); _appendButton.frame = LayoutRectGetRect(rightAccessoryLayout); - _physicalWebImageView.frame = LayoutRectGetRect(rightAccessoryLayout); + _physicalWebButton.frame = LayoutRectGetRect(rightAccessoryLayout); } - (void)updateLeftImage:(int)imageID { @@ -168,6 +167,16 @@ forState:UIControlStateHighlighted]; } +- (void)updatePhysicalWebImage { + UIImage* physicalWebImage = NativeImage(IDR_IOS_OMNIBOX_PHYSICAL_WEB); + [_physicalWebButton setImage:physicalWebImage forState:UIControlStateNormal]; + + UIImage* physicalWebImageSelected = + NativeImage(IDR_IOS_OMNIBOX_PHYSICAL_WEB_HIGHLIGHTED); + [_physicalWebButton setImage:physicalWebImageSelected + forState:UIControlStateHighlighted]; +} + - (NSString*)accessibilityLabel { return _textTruncatingLabel.attributedText.string; }
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_popup_material_view_controller.mm b/ios/chrome/browser/ui/omnibox/omnibox_popup_material_view_controller.mm index 29c71449f..f408e9c2 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_popup_material_view_controller.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_popup_material_view_controller.mm
@@ -9,6 +9,7 @@ #include "base/ios/ios_util.h" #include "base/mac/scoped_cftyperef.h" #include "base/mac/scoped_nsobject.h" +#include "base/metrics/user_metrics.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" #include "components/omnibox/browser/autocomplete_input.h" @@ -16,6 +17,8 @@ #include "components/omnibox/browser/autocomplete_result.h" #include "components/omnibox/browser/suggestion_answer.h" #include "ios/chrome/browser/ui/animation_util.h" +#import "ios/chrome/browser/ui/commands/generic_chrome_command.h" +#include "ios/chrome/browser/ui/commands/ios_command_ids.h" #import "ios/chrome/browser/ui/omnibox/omnibox_popup_material_row.h" #import "ios/chrome/browser/ui/omnibox/omnibox_popup_view_ios.h" #include "ios/chrome/browser/ui/omnibox/omnibox_util.h" @@ -183,6 +186,9 @@ action:@selector(appendButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; [row.appendButton setTag:i]; + [row.physicalWebButton addTarget:self + action:@selector(physicalWebButtonTapped:) + forControlEvents:UIControlEventTouchUpInside]; row.rowHeight = kRowHeight; } _rows.reset([rowsBuilder copy]); @@ -384,7 +390,8 @@ BOOL physicalWebMatch = match.type == AutocompleteMatchType::PHYSICAL_WEB || match.type == AutocompleteMatchType::PHYSICAL_WEB_OVERFLOW; - row.physicalWebImageView.hidden = !physicalWebMatch; + row.physicalWebButton.hidden = !physicalWebMatch; + [row.physicalWebButton cancelTrackingWithEvent:nil]; // If a right accessory element is present or the text alignment is right // aligned, adjust the width to align with the accessory element. @@ -645,6 +652,16 @@ _popupView->CopyToOmnibox(contents); } +- (void)physicalWebButtonTapped:(id)sender { + base::scoped_nsobject<GenericChromeCommand> command([ + [GenericChromeCommand alloc] initWithTag:IDC_SHOW_PHYSICAL_WEB_SETTINGS]); + [command executeOnMainWindow]; + + // Record when the user opens the Physical Web preference page from the + // omnibox suggestion. + base::RecordAction(base::UserMetricsAction("PhysicalWeb.Prefs.FromOmnibox")); +} + #pragma mark - #pragma mark UIScrollViewDelegate
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.h b/ios/chrome/browser/ui/settings/settings_navigation_controller.h index 3532e5e..3b2c1bd 100644 --- a/ios/chrome/browser/ui/settings/settings_navigation_controller.h +++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.h
@@ -109,6 +109,13 @@ newSavePasswordsController:(ios::ChromeBrowserState*)browserState delegate:(id<SettingsNavigationControllerDelegate>)delegate; +// Creates and displays a new PhysicalWebCollectionViewController and the chrome +// around it. |browserState| is used to personalize some settings aspects and +// should not be null. |delegate| may be nil. ++ (SettingsNavigationController*) +newPhysicalWebController:(ios::ChromeBrowserState*)browserState + delegate:(id<SettingsNavigationControllerDelegate>)delegate; + // Creates and displays a new UserFeedbackViewController. |browserState| is used // to personalize some settings aspects and should not be nil. |dataSource| is // used to populate the UserFeedbackViewController. |delegate| may be nil.
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm index 7940e97..bdf380b 100644 --- a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
@@ -9,6 +9,7 @@ #include "base/mac/foundation_util.h" #import "base/mac/scoped_nsobject.h" #include "components/strings/grit/components_strings.h" +#include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/sync/sync_setup_service.h" #include "ios/chrome/browser/sync/sync_setup_service_factory.h" @@ -25,6 +26,7 @@ #import "ios/chrome/browser/ui/settings/contextual_search_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/import_data_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/native_apps_collection_view_controller.h" +#import "ios/chrome/browser/ui/settings/physical_web_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/save_passwords_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/settings_utils.h" @@ -258,6 +260,20 @@ } + (SettingsNavigationController*) +newPhysicalWebController:(ios::ChromeBrowserState*)browserState + delegate:(id<SettingsNavigationControllerDelegate>)delegate { + base::scoped_nsobject<UIViewController> controller( + [[PhysicalWebCollectionViewController alloc] + initWithPrefs:GetApplicationContext()->GetLocalState()]); + SettingsNavigationController* nc = [[SettingsNavigationController alloc] + initWithRootViewController:controller + browserState:browserState + delegate:delegate]; + [controller navigationItem].rightBarButtonItem = [nc doneButton]; + return nc; +} + ++ (SettingsNavigationController*) newImportDataController:(ios::ChromeBrowserState*)browserState delegate:(id<SettingsNavigationControllerDelegate>)delegate importDataDelegate:(id<ImportDataControllerDelegate>)importDataDelegate
diff --git a/mash/task_viewer/task_viewer.cc b/mash/task_viewer/task_viewer.cc index cd9d8a4..30025d44 100644 --- a/mash/task_viewer/task_viewer.cc +++ b/mash/task_viewer/task_viewer.cc
@@ -146,7 +146,7 @@ // Overridden from views::ButtonListener: void ButtonPressed(views::Button* sender, const ui::Event& event) override { DCHECK_EQ(sender, kill_button_); - DCHECK_EQ(table_view_->SelectedRowCount(), 1); + DCHECK_EQ(table_view_->selection_model().size(), 1UL); int row = table_view_->FirstSelectedRow(); DCHECK(row < static_cast<int>(instances_.size())); base::Process process = base::Process::Open(instances_[row]->pid);
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 654ba89..c6b8b571ce 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -346,14 +346,21 @@ } void WebMediaPlayerImpl::enteredFullscreen() { - if (!force_video_overlays_ && enable_fullscreen_video_overlays_) + // |force_video_overlays_| implies that we're already in overlay mode, so take + // no action here. Otherwise, switch to an overlay if it's allowed and if + // it will display properly. + if (!force_video_overlays_ && enable_fullscreen_video_overlays_ && + DoesOverlaySupportMetadata()) { EnableOverlay(); + } if (observer_) observer_->OnEnteredFullscreen(); } void WebMediaPlayerImpl::exitedFullscreen() { - if (!force_video_overlays_ && enable_fullscreen_video_overlays_) + // If we're in overlay mode, then exit it unless we're supposed to be in + // overlay mode all the time. + if (!force_video_overlays_ && overlay_enabled_) DisableOverlay(); if (observer_) observer_->OnExitedFullscreen(); @@ -1155,8 +1162,15 @@ pipeline_metadata_.natural_size = GetRotatedVideoSize( pipeline_metadata_.video_rotation, pipeline_metadata_.natural_size); - if (overlay_enabled_ && surface_manager_) - surface_manager_->NaturalSizeChanged(pipeline_metadata_.natural_size); + if (overlay_enabled_) { + // SurfaceView doesn't support rotated video, so transition back if + // the video is now rotated. If |force_video_overlays_|, we keep the + // overlay anyway so that the state machine keeps working. + if (!force_video_overlays_ && !DoesOverlaySupportMetadata()) + DisableOverlay(); + else if (surface_manager_) + surface_manager_->NaturalSizeChanged(pipeline_metadata_.natural_size); + } DCHECK(!video_weblayer_); video_weblayer_.reset(new cc_blink::WebLayerImpl(cc::VideoLayer::Create( @@ -2011,6 +2025,10 @@ return delegate_ && delegate_->IsHidden(); } +bool WebMediaPlayerImpl::DoesOverlaySupportMetadata() const { + return pipeline_metadata_.video_rotation == VIDEO_ROTATION_0; +} + void WebMediaPlayerImpl::ActivateViewportIntersectionMonitoring(bool activate) { DCHECK(main_task_runner_->BelongsToCurrentThread());
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h index 711799d..5aa465c 100644 --- a/media/blink/webmediaplayer_impl.h +++ b/media/blink/webmediaplayer_impl.h
@@ -363,6 +363,10 @@ // Returns true if the player is hidden. bool IsHidden() const; + // Return whether |pipeline_metadata_| is compatible with an overlay. This + // is intended for android. + bool DoesOverlaySupportMetadata() const; + blink::WebLocalFrame* frame_; // The playback state last reported to |delegate_|, to avoid setting duplicate
diff --git a/media/capture/video/video_capture_device.h b/media/capture/video/video_capture_device.h index dc0b77f..e561267 100644 --- a/media/capture/video/video_capture_device.h +++ b/media/capture/video/video_capture_device.h
@@ -41,6 +41,15 @@ namespace media { +class CAPTURE_EXPORT FrameBufferPool { + public: + virtual ~FrameBufferPool() {} + + virtual void SetBufferHold(int buffer_id) = 0; + virtual void ReleaseBufferHold(int buffer_id) = 0; + virtual mojo::ScopedSharedBufferHandle GetHandleForTransit(int buffer_id) = 0; +}; + class CAPTURE_EXPORT VideoFrameConsumerFeedbackObserver { public: virtual ~VideoFrameConsumerFeedbackObserver() {} @@ -148,11 +157,10 @@ // |timestamp|. // TODO(chfremer): Consider removing one of the two in order to simplify the // interface. - virtual void OnIncomingCapturedBuffer( - std::unique_ptr<Buffer> buffer, - const VideoCaptureFormat& frame_format, - base::TimeTicks reference_time, - base::TimeDelta timestamp) = 0; + virtual void OnIncomingCapturedBuffer(std::unique_ptr<Buffer> buffer, + const VideoCaptureFormat& format, + base::TimeTicks reference_time, + base::TimeDelta timestamp) = 0; virtual void OnIncomingCapturedVideoFrame( std::unique_ptr<Buffer> buffer, scoped_refptr<VideoFrame> frame) = 0;
diff --git a/media/capture/video/video_capture_device_client.cc b/media/capture/video/video_capture_device_client.cc index ab0b916..3321633 100644 --- a/media/capture/video/video_capture_device_client.cc +++ b/media/capture/video/video_capture_device_client.cc
@@ -95,20 +95,20 @@ void VideoCaptureDeviceClient::OnIncomingCapturedData( const uint8_t* data, int length, - const VideoCaptureFormat& frame_format, + const VideoCaptureFormat& format, int rotation, base::TimeTicks reference_time, base::TimeDelta timestamp, int frame_feedback_id) { TRACE_EVENT0("video", "VideoCaptureDeviceClient::OnIncomingCapturedData"); - DCHECK_EQ(media::PIXEL_STORAGE_CPU, frame_format.pixel_storage); + DCHECK_EQ(media::PIXEL_STORAGE_CPU, format.pixel_storage); - if (last_captured_pixel_format_ != frame_format.pixel_format) { + if (last_captured_pixel_format_ != format.pixel_format) { OnLog("Pixel format: " + - media::VideoPixelFormatToString(frame_format.pixel_format)); - last_captured_pixel_format_ = frame_format.pixel_format; + media::VideoPixelFormatToString(format.pixel_format)); + last_captured_pixel_format_ = format.pixel_format; - if (frame_format.pixel_format == media::PIXEL_FORMAT_MJPEG && + if (format.pixel_format == media::PIXEL_FORMAT_MJPEG && !external_jpeg_decoder_initialized_) { external_jpeg_decoder_initialized_ = true; external_jpeg_decoder_ = jpeg_decoder_factory_callback_.Run(); @@ -116,20 +116,20 @@ } } - if (!frame_format.IsValid()) + if (!format.IsValid()) return; - if (frame_format.pixel_format == media::PIXEL_FORMAT_Y16) { - return OnIncomingCapturedY16Data(data, length, frame_format, reference_time, + if (format.pixel_format == media::PIXEL_FORMAT_Y16) { + return OnIncomingCapturedY16Data(data, length, format, reference_time, timestamp, frame_feedback_id); } // |chopped_{width,height} and |new_unrotated_{width,height}| are the lowest // bit decomposition of {width, height}, grabbing the odd and even parts. - const int chopped_width = frame_format.frame_size.width() & 1; - const int chopped_height = frame_format.frame_size.height() & 1; - const int new_unrotated_width = frame_format.frame_size.width() & ~1; - const int new_unrotated_height = frame_format.frame_size.height() & ~1; + const int chopped_width = format.frame_size.width() & 1; + const int chopped_height = format.frame_size.height() & 1; + const int new_unrotated_width = format.frame_size.width() & ~1; + const int new_unrotated_height = format.frame_size.height() & ~1; int destination_width = new_unrotated_width; int destination_height = new_unrotated_height; @@ -167,7 +167,7 @@ libyuv::FourCC origin_colorspace = libyuv::FOURCC_ANY; bool flip = false; - switch (frame_format.pixel_format) { + switch (format.pixel_format) { case media::PIXEL_FORMAT_UNKNOWN: // Color format not set. break; case media::PIXEL_FORMAT_I420: @@ -232,7 +232,7 @@ // The input |length| can be greater than the required buffer size because of // paddings and/or alignments, but it cannot be smaller. - DCHECK_GE(static_cast<size_t>(length), frame_format.ImageAllocationSize()); + DCHECK_GE(static_cast<size_t>(length), format.ImageAllocationSize()); if (external_jpeg_decoder_) { const VideoCaptureJpegDecoder::STATUS status = @@ -240,29 +240,27 @@ if (status == VideoCaptureJpegDecoder::FAILED) { external_jpeg_decoder_.reset(); } else if (status == VideoCaptureJpegDecoder::INIT_PASSED && - frame_format.pixel_format == media::PIXEL_FORMAT_MJPEG && + format.pixel_format == media::PIXEL_FORMAT_MJPEG && rotation == 0 && !flip) { - external_jpeg_decoder_->DecodeCapturedData(data, length, frame_format, - reference_time, timestamp, - std::move(buffer)); + external_jpeg_decoder_->DecodeCapturedData( + data, length, format, reference_time, timestamp, std::move(buffer)); return; } } - if (libyuv::ConvertToI420(data, length, y_plane_data, yplane_stride, - u_plane_data, uv_plane_stride, v_plane_data, - uv_plane_stride, crop_x, crop_y, - frame_format.frame_size.width(), - (flip ? -1 : 1) * frame_format.frame_size.height(), - new_unrotated_width, new_unrotated_height, - rotation_mode, origin_colorspace) != 0) { + if (libyuv::ConvertToI420( + data, length, y_plane_data, yplane_stride, u_plane_data, + uv_plane_stride, v_plane_data, uv_plane_stride, crop_x, crop_y, + format.frame_size.width(), + (flip ? -1 : 1) * format.frame_size.height(), new_unrotated_width, + new_unrotated_height, rotation_mode, origin_colorspace) != 0) { DLOG(WARNING) << "Failed to convert buffer's pixel format to I420 from " - << media::VideoPixelFormatToString(frame_format.pixel_format); + << media::VideoPixelFormatToString(format.pixel_format); return; } const VideoCaptureFormat output_format = - VideoCaptureFormat(dimensions, frame_format.frame_rate, + VideoCaptureFormat(dimensions, format.frame_rate, media::PIXEL_FORMAT_I420, media::PIXEL_STORAGE_CPU); OnIncomingCapturedBuffer(std::move(buffer), output_format, reference_time, timestamp); @@ -294,11 +292,11 @@ void VideoCaptureDeviceClient::OnIncomingCapturedBuffer( std::unique_ptr<Buffer> buffer, - const VideoCaptureFormat& frame_format, + const VideoCaptureFormat& format, base::TimeTicks reference_time, base::TimeDelta timestamp) { - DCHECK(IsFormatSupported(frame_format.pixel_format)); - DCHECK_EQ(media::PIXEL_STORAGE_CPU, frame_format.pixel_storage); + DCHECK(IsFormatSupported(format.pixel_format)); + DCHECK_EQ(media::PIXEL_STORAGE_CPU, format.pixel_storage); scoped_refptr<VideoFrame> frame; if (buffer->IsBackedByVideoFrame()) { @@ -306,17 +304,15 @@ frame->set_timestamp(timestamp); } else { frame = VideoFrame::WrapExternalSharedMemory( - frame_format.pixel_format, frame_format.frame_size, - gfx::Rect(frame_format.frame_size), frame_format.frame_size, - reinterpret_cast<uint8_t*>(buffer->data()), - VideoFrame::AllocationSize(frame_format.pixel_format, - frame_format.frame_size), + format.pixel_format, format.frame_size, gfx::Rect(format.frame_size), + format.frame_size, reinterpret_cast<uint8_t*>(buffer->data()), + VideoFrame::AllocationSize(format.pixel_format, format.frame_size), base::SharedMemory::NULLHandle(), 0u, timestamp); } if (!frame) return; frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, - frame_format.frame_rate); + format.frame_rate); frame->metadata()->SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME, reference_time); OnIncomingCapturedVideoFrame(std::move(buffer), std::move(frame)); @@ -395,16 +391,16 @@ void VideoCaptureDeviceClient::OnIncomingCapturedY16Data( const uint8_t* data, int length, - const VideoCaptureFormat& frame_format, + const VideoCaptureFormat& format, base::TimeTicks reference_time, base::TimeDelta timestamp, int frame_feedback_id) { std::unique_ptr<Buffer> buffer( - ReserveOutputBuffer(frame_format.frame_size, media::PIXEL_FORMAT_Y16, + ReserveOutputBuffer(format.frame_size, media::PIXEL_FORMAT_Y16, media::PIXEL_STORAGE_CPU, frame_feedback_id)); // The input |length| can be greater than the required buffer size because of // paddings and/or alignments, but it cannot be smaller. - DCHECK_GE(static_cast<size_t>(length), frame_format.ImageAllocationSize()); + DCHECK_GE(static_cast<size_t>(length), format.ImageAllocationSize()); #if DCHECK_IS_ON() dropped_frame_counter_ = buffer.get() ? 0 : dropped_frame_counter_ + 1; if (dropped_frame_counter_ >= kMaxDroppedFrames) @@ -415,7 +411,7 @@ return; memcpy(buffer->data(), data, length); const VideoCaptureFormat output_format = - VideoCaptureFormat(frame_format.frame_size, frame_format.frame_rate, + VideoCaptureFormat(format.frame_size, format.frame_rate, media::PIXEL_FORMAT_Y16, media::PIXEL_STORAGE_CPU); OnIncomingCapturedBuffer(std::move(buffer), output_format, reference_time, timestamp);
diff --git a/mojo/common/BUILD.gn b/mojo/common/BUILD.gn index 60d523f..7258650 100644 --- a/mojo/common/BUILD.gn +++ b/mojo/common/BUILD.gn
@@ -32,11 +32,8 @@ "common_type_converters.h", "data_pipe_drainer.cc", "data_pipe_drainer.h", - "data_pipe_file_utils.cc", "data_pipe_utils.cc", "data_pipe_utils.h", - "user_agent.cc", - "user_agent.h", ] defines = [ "MOJO_COMMON_IMPLEMENTATION" ]
diff --git a/mojo/common/DEPS b/mojo/common/DEPS index f3e298f..e8ac4288 100644 --- a/mojo/common/DEPS +++ b/mojo/common/DEPS
@@ -1,16 +1,6 @@ include_rules = [ # common must not depend on embedder. "-mojo", - "+services/service_manager/public/cpp", "+mojo/common", "+mojo/public", ] - -specific_include_rules = { - "trace_controller_impl\.h": [ - "+services/tracing/public/interfaces/tracing.mojom.h" - ], - "tracing_impl\.h": [ - "+services/tracing/public/interfaces/tracing.mojom.h" - ], -}
diff --git a/mojo/common/data_pipe_file_utils.cc b/mojo/common/data_pipe_file_utils.cc deleted file mode 100644 index 841dfde9..0000000 --- a/mojo/common/data_pipe_file_utils.cc +++ /dev/null
@@ -1,81 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/common/data_pipe_utils.h" - -#include <stdint.h> - -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/files/scoped_file.h" -#include "base/location.h" -#include "base/task_runner_util.h" - -namespace mojo { -namespace common { -namespace { - -bool BlockingCopyFromFile(const base::FilePath& source, - ScopedDataPipeProducerHandle destination, - uint32_t skip) { - base::File file(source, base::File::FLAG_OPEN | base::File::FLAG_READ); - if (!file.IsValid()) - return false; - if (file.Seek(base::File::FROM_BEGIN, skip) != skip) { - LOG(ERROR) << "Seek of " << skip << " in " << source.value() << " failed"; - return false; - } - for (;;) { - void* buffer = nullptr; - uint32_t buffer_num_bytes = 0; - MojoResult result = - BeginWriteDataRaw(destination.get(), &buffer, &buffer_num_bytes, - MOJO_WRITE_DATA_FLAG_NONE); - if (result == MOJO_RESULT_OK) { - int bytes_read = - file.ReadAtCurrentPos(static_cast<char*>(buffer), buffer_num_bytes); - if (bytes_read >= 0) { - EndWriteDataRaw(destination.get(), bytes_read); - if (bytes_read == 0) { - // eof - return true; - } - } else { - // error - EndWriteDataRaw(destination.get(), 0); - return false; - } - } else if (result == MOJO_RESULT_SHOULD_WAIT) { - result = Wait(destination.get(), MOJO_HANDLE_SIGNAL_WRITABLE, - MOJO_DEADLINE_INDEFINITE, nullptr); - if (result != MOJO_RESULT_OK) { - // If the consumer handle was closed, then treat as EOF. - return result == MOJO_RESULT_FAILED_PRECONDITION; - } - } else { - // If the consumer handle was closed, then treat as EOF. - return result == MOJO_RESULT_FAILED_PRECONDITION; - } - } -#if !defined(OS_WIN) - NOTREACHED(); - return false; -#endif -} - -} // namespace - -void CopyFromFile(const base::FilePath& source, - ScopedDataPipeProducerHandle destination, - uint32_t skip, - base::TaskRunner* task_runner, - const base::Callback<void(bool)>& callback) { - base::PostTaskAndReplyWithResult(task_runner, FROM_HERE, - base::Bind(&BlockingCopyFromFile, source, - base::Passed(&destination), skip), - callback); -} - -} // namespace common -} // namespace mojo
diff --git a/mojo/common/data_pipe_utils.cc b/mojo/common/data_pipe_utils.cc index 8540ac63..bed5e85 100644 --- a/mojo/common/data_pipe_utils.cc +++ b/mojo/common/data_pipe_utils.cc
@@ -4,16 +4,9 @@ #include "mojo/common/data_pipe_utils.h" -#include <stddef.h> -#include <stdint.h> -#include <stdio.h> #include <utility> -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/files/scoped_file.h" -#include "base/message_loop/message_loop.h" -#include "base/task_runner_util.h" +#include "base/bind.h" namespace mojo { namespace common { @@ -58,12 +51,7 @@ return num_bytes; } -size_t CopyToFileHelper(FILE* fp, const void* buffer, uint32_t num_bytes) { - return fwrite(buffer, 1, num_bytes, fp); -} - -} // namespace - +} // namespace // TODO(hansmuller): Add a max_size parameter. bool BlockingCopyToString(ScopedDataPipeConsumerHandle source, @@ -107,25 +95,5 @@ } } -bool BlockingCopyToFile(ScopedDataPipeConsumerHandle source, - const base::FilePath& destination) { - base::ScopedFILE fp(base::OpenFile(destination, "wb")); - if (!fp) - return false; - return BlockingCopyHelper(std::move(source), - base::Bind(&CopyToFileHelper, fp.get())); -} - -void CopyToFile(ScopedDataPipeConsumerHandle source, - const base::FilePath& destination, - base::TaskRunner* task_runner, - const base::Callback<void(bool)>& callback) { - base::PostTaskAndReplyWithResult( - task_runner, - FROM_HERE, - base::Bind(&BlockingCopyToFile, base::Passed(&source), destination), - callback); -} - } // namespace common } // namespace mojo
diff --git a/mojo/common/data_pipe_utils.h b/mojo/common/data_pipe_utils.h index 426912c..a3f7c093 100644 --- a/mojo/common/data_pipe_utils.h +++ b/mojo/common/data_pipe_utils.h
@@ -2,41 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef MOJO_SHELL_DATA_PIPE_UTILS_H_ -#define MOJO_SHELL_DATA_PIPE_UTILS_H_ +#ifndef MOJO_COMMON_DATA_PIPE_UTILS_H_ +#define MOJO_COMMON_DATA_PIPE_UTILS_H_ #include <stdint.h> #include <string> -#include "base/callback_forward.h" #include "mojo/common/mojo_common_export.h" -#include "mojo/public/cpp/system/core.h" - -namespace base { -class FilePath; -class TaskRunner; -} +#include "mojo/public/cpp/system/data_pipe.h" namespace mojo { namespace common { -// Asynchronously copies data from source to the destination file. The given -// |callback| is run upon completion. File writes will be scheduled to the -// given |task_runner|. -void MOJO_COMMON_EXPORT CopyToFile( - ScopedDataPipeConsumerHandle source, - const base::FilePath& destination, - base::TaskRunner* task_runner, - const base::Callback<void(bool /*success*/)>& callback); - -void MOJO_COMMON_EXPORT -CopyFromFile(const base::FilePath& source, - ScopedDataPipeProducerHandle destination, - uint32_t skip, - base::TaskRunner* task_runner, - const base::Callback<void(bool /*success*/)>& callback); - // Copies the data from |source| into |contents| and returns true on success and // false on error. In case of I/O error, |contents| holds the data that could // be read from source before the error occurred. @@ -48,13 +26,7 @@ const std::string& source, const ScopedDataPipeProducerHandle& destination); -// Synchronously copies data from source to the destination file returning true -// on success and false on error. In case of an error, |destination| holds the -// data that could be read from the source before the error occured. -bool MOJO_COMMON_EXPORT BlockingCopyToFile(ScopedDataPipeConsumerHandle source, - const base::FilePath& destination); - } // namespace common } // namespace mojo -#endif // MOJO_SHELL_DATA_PIPE_UTILS_H_ +#endif // MOJO_COMMON_DATA_PIPE_UTILS_H_
diff --git a/mojo/common/user_agent.cc b/mojo/common/user_agent.cc deleted file mode 100644 index 6055cbe5a..0000000 --- a/mojo/common/user_agent.cc +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/common/user_agent.h" - -#include "build/build_config.h" - -namespace mojo { -namespace common { - -std::string GetUserAgent() { - // TODO(jam): change depending on OS -#if defined(OS_ANDROID) - return "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY48G) " - "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.68 " - "Safari/537.36"; -#else - return "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like " - "Gecko) Chrome/42.0.2311.68 Safari/537.36"; -#endif -} - -} // namespace common -} // namespace mojo
diff --git a/mojo/common/user_agent.h b/mojo/common/user_agent.h deleted file mode 100644 index 031b1029..0000000 --- a/mojo/common/user_agent.h +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_COMMON_USER_AGENT_H_ -#define MOJO_COMMON_USER_AGENT_H_ - -#include <string> - -#include "mojo/common/mojo_common_export.h" - -namespace mojo { -namespace common { - -std::string MOJO_COMMON_EXPORT GetUserAgent(); - -} // namespace common -} // namespace mojo - -#endif // MOJO_COMMON_USER_AGENT_H_
diff --git a/net/log/net_log_event_type_list.h b/net/log/net_log_event_type_list.h index 37cb814..e7b4227f 100644 --- a/net/log/net_log_event_type_list.h +++ b/net/log/net_log_event_type_list.h
@@ -850,7 +850,7 @@ // Logged when a delegate informs the URL_REQUEST of what's currently blocking // the request. The parameters attached to the begin event are: // { -// "delegate_info": <Information about what's blocking the request>, +// "delegate_blocked_by": <Information about what's blocking the request>, // } EVENT_TYPE(DELEGATE_INFO) @@ -3030,3 +3030,13 @@ // the end of file. Result < 0 means an error.> // } EVENT_TYPE(UPLOAD_DATA_STREAM_READ) + +// ----------------------------------------------------------------------------- +// ResourceScheduler related events +// ----------------------------------------------------------------------------- + +// The ResourceScheduler has started a previously blocked request. Parameters: +// { +// "trigger": <Trigger for evaluation that caused request start> +// } +EVENT_TYPE(RESOURCE_SCHEDULER_REQUEST_STARTED)
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index 75eb422..f687bec 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc
@@ -294,7 +294,7 @@ if (!load_state.param.empty()) dict->SetString("load_state_param", load_state.param); if (!blocked_by_.empty()) - dict->SetString("delegate_info", blocked_by_); + dict->SetString("delegate_blocked_by", blocked_by_); dict->SetString("method", method_); dict->SetBoolean("has_upload", has_upload()); @@ -335,8 +335,9 @@ blocked_by_ = blocked_by; use_blocked_by_as_load_param_ = false; - net_log_.BeginEvent(NetLogEventType::DELEGATE_INFO, - NetLog::StringCallback("delegate_info", &blocked_by_)); + net_log_.BeginEvent( + NetLogEventType::DELEGATE_INFO, + NetLog::StringCallback("delegate_blocked_by", &blocked_by_)); } void URLRequest::LogAndReportBlockedBy(const char* source) { @@ -584,7 +585,9 @@ DCHECK(base::ThreadTaskRunnerHandle::IsSet()); context->url_requests()->insert(this); - net_log_.BeginEvent(NetLogEventType::REQUEST_ALIVE); + net_log_.BeginEvent( + NetLogEventType::REQUEST_ALIVE, + base::Bind(&NetLogURLRequestConstructorCallback, &url, priority_)); } void URLRequest::BeforeRequestComplete(int error) { @@ -627,7 +630,6 @@ net_log_.BeginEvent( NetLogEventType::URL_REQUEST_START_JOB, base::Bind(&NetLogURLRequestStartCallback, &url(), &method_, load_flags_, - priority_, upload_data_stream_ ? upload_data_stream_->identifier() : -1)); job_.reset(job); @@ -1024,12 +1026,11 @@ return; priority_ = priority; - if (job_.get()) { - net_log_.AddEvent( - NetLogEventType::URL_REQUEST_SET_PRIORITY, - NetLog::StringCallback("priority", RequestPriorityToString(priority_))); + net_log_.AddEvent( + NetLogEventType::URL_REQUEST_SET_PRIORITY, + NetLog::StringCallback("priority", RequestPriorityToString(priority_))); + if (job_.get()) job_->SetPriority(priority_); - } } void URLRequest::NotifyAuthRequired(AuthChallengeInfo* auth_info) {
diff --git a/net/url_request/url_request_netlog_params.cc b/net/url_request/url_request_netlog_params.cc index 97b67bad..9fc0f22 100644 --- a/net/url_request/url_request_netlog_params.cc +++ b/net/url_request/url_request_netlog_params.cc
@@ -13,18 +13,26 @@ namespace net { +std::unique_ptr<base::Value> NetLogURLRequestConstructorCallback( + const GURL* url, + RequestPriority priority, + NetLogCaptureMode /* capture_mode */) { + std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); + dict->SetString("url", url->possibly_invalid_spec()); + dict->SetString("priority", RequestPriorityToString(priority)); + return std::move(dict); +} + std::unique_ptr<base::Value> NetLogURLRequestStartCallback( const GURL* url, const std::string* method, int load_flags, - RequestPriority priority, int64_t upload_id, NetLogCaptureMode /* capture_mode */) { std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); dict->SetString("url", url->possibly_invalid_spec()); dict->SetString("method", *method); dict->SetInteger("load_flags", load_flags); - dict->SetString("priority", RequestPriorityToString(priority)); if (upload_id > -1) dict->SetString("upload_id", base::Int64ToString(upload_id)); return std::move(dict);
diff --git a/net/url_request/url_request_netlog_params.h b/net/url_request/url_request_netlog_params.h index a42ca3f3..2d672f5 100644 --- a/net/url_request/url_request_netlog_params.h +++ b/net/url_request/url_request_netlog_params.h
@@ -23,12 +23,17 @@ class NetLogCaptureMode; +// Returns a Value containing NetLog parameters for constructing a URLRequest. +NET_EXPORT std::unique_ptr<base::Value> NetLogURLRequestConstructorCallback( + const GURL* url, + RequestPriority priority, + NetLogCaptureMode /* capture_mode */); + // Returns a Value containing NetLog parameters for starting a URLRequest. NET_EXPORT std::unique_ptr<base::Value> NetLogURLRequestStartCallback( const GURL* url, const std::string* method, int load_flags, - RequestPriority priority, int64_t upload_id, NetLogCaptureMode /* capture_mode */);
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 616eb319..e5c941f 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -4861,7 +4861,7 @@ std::string delegate_info; EXPECT_EQ(NetLogEventType::DELEGATE_INFO, entries[log_position].type); EXPECT_EQ(NetLogEventPhase::BEGIN, entries[log_position].phase); - EXPECT_TRUE(entries[log_position].GetStringValue("delegate_info", + EXPECT_TRUE(entries[log_position].GetStringValue("delegate_blocked_by", &delegate_info)); EXPECT_EQ(kFirstDelegateInfo, delegate_info); @@ -4872,7 +4872,7 @@ ++log_position; EXPECT_EQ(NetLogEventType::DELEGATE_INFO, entries[log_position].type); EXPECT_EQ(NetLogEventPhase::BEGIN, entries[log_position].phase); - EXPECT_TRUE(entries[log_position].GetStringValue("delegate_info", + EXPECT_TRUE(entries[log_position].GetStringValue("delegate_blocked_by", &delegate_info)); EXPECT_EQ(kSecondDelegateInfo, delegate_info);
diff --git a/skia/BUILD.gn b/skia/BUILD.gn index d4d5672..904502a 100644 --- a/skia/BUILD.gn +++ b/skia/BUILD.gn
@@ -41,7 +41,10 @@ "//third_party/skia/include/utils", ] - defines = [ "SK_IGNORE_DW_GRAY_FIX" ] + defines = [ + "SK_IGNORE_DW_GRAY_FIX", + "SK_LEGACY_FONTMGR_FACTORY", + ] defines += skia_for_chromium_defines defines += []
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 6b0390a..42adfe5 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2340,8 +2340,6 @@ crbug.com/664855 virtual/scroll_customization/fast/scroll-behavior/main-frame-interrupted-scroll.html [ Pass Failure ] crbug.com/664856 virtual/sharedarraybuffer/fast/workers/worker-gc.html [ Pass Failure ] -crbug.com/664857 virtual/threaded/animations/composited-animations-simple.html [ Pass Failure ] - # Possible duplicate of crbug.com/665577 # crbug.com/664858 virtual/threaded/fast/scroll-behavior/overflow-scroll-animates.html [ Pass Failure ] # crbug.com/664858 virtual/threaded/fast/scroll-behavior/smooth-scroll/horizontal-smooth-scroll-in-rtl.html [ Pass Failure ]
diff --git a/third_party/WebKit/LayoutTests/animations/resources/composited-animation-test.js b/third_party/WebKit/LayoutTests/animations/resources/composited-animation-test.js index dfdbd3a129..3b5fc00 100644 --- a/third_party/WebKit/LayoutTests/animations/resources/composited-animation-test.js +++ b/third_party/WebKit/LayoutTests/animations/resources/composited-animation-test.js
@@ -139,15 +139,21 @@ this.error.textContent += `${test.name}: ${message} `; } + waitForCompositor() { + return this.error.animate({opacity: ['1', '1']}, 1).ready; + } + layoutAndPaint() { if (window.testRunner) testRunner.waitUntilDone(); - requestAnimationFrame(() => { - if (window.internals) - this.assertAnimationCompositedState(); - if (window.testRunner) - testRunner.notifyDone(); + this.waitForCompositor().then(() => { + requestAnimationFrame(() => { + if (window.internals) + this.assertAnimationCompositedState(); + if (window.testRunner) + testRunner.notifyDone(); + }); }); }
diff --git a/third_party/WebKit/LayoutTests/vr/resources/mock-vr-service.js b/third_party/WebKit/LayoutTests/vr/resources/mock-vr-service.js index 7946790..a4864ee 100644 --- a/third_party/WebKit/LayoutTests/vr/resources/mock-vr-service.js +++ b/third_party/WebKit/LayoutTests/vr/resources/mock-vr-service.js
@@ -3,23 +3,17 @@ let mockVRService = loadMojoModules( 'mockVRService', ['mojo/public/js/bindings', - 'mojo/public/js/connection', - 'mojo/public/js/router', 'device/vr/vr_service.mojom', ]).then(mojo => { - let [bindings, connection, router, vr_service] = mojo.modules; + let [bindings, vr_service] = mojo.modules; - class MockVRDisplay extends vr_service.VRDisplay.stubClass { + class MockVRDisplay { constructor(interfaceProvider) { - super(); + this.bindingSet_ = new bindings.BindingSet(vr_service.VRDisplay); + interfaceProvider.addInterfaceOverrideForTesting( vr_service.VRDisplay.name, - handle => this.connect_(handle)); - } - - connect_(handle) { - this.router_ = new router.Router(handle); - this.router_.setIncomingReceiver(this); + handle => this.bindingSet_.addBinding(this, handle)); } requestPresent(secureOrigin) { @@ -27,42 +21,36 @@ } } - class MockVRService extends vr_service.VRService.stubClass { + class MockVRService { constructor(interfaceProvider) { - super(); + this.bindingSet_ = new bindings.BindingSet(vr_service.VRService); + this.displayClient_ = new vr_service.VRDisplayClientPtr(); + this.vrDisplays_ = null; + interfaceProvider.addInterfaceOverrideForTesting( vr_service.VRService.name, - handle => this.connect_(handle)); - this.vr_displays_ = null; - } - - connect_(handle) { - this.router_ = new router.Router(handle); - this.router_.setIncomingReceiver(this); + handle => this.bindingSet_.addBinding(this, handle)); } setVRDisplays(displays) { for (let i = 0; i < displays.length; i++) { displays[i].index = i; } - this.vr_displays_ = displays; + this.vrDisplays_ = displays; } notifyClientOfDisplays() { - if (this.vr_displays_ == null) { + if (this.vrDisplays_ == null) { return; } - for (let i = 0; i < this.vr_displays_.length; i++) { + for (let i = 0; i < this.vrDisplays_.length; i++) { let displayPtr = new vr_service.VRDisplayPtr(); let request = bindings.makeRequest(displayPtr); let binding = new bindings.Binding( vr_service.VRDisplay, new MockVRDisplay(mojo.frameInterfaces), request); - let client_handle = new bindings.InterfaceRequest( - connection.bindProxy(proxy => { - this.displayClient_ = proxy; - }, vr_service.VRDisplayClient)); - this.client_.onDisplayConnected(displayPtr, client_handle, this.vr_displays_[i]); + let clientRequest = bindings.makeRequest(this.displayClient_); + this.client_.onDisplayConnected(displayPtr, clientRequest, this.vrDisplays_[i]); } } @@ -70,7 +58,7 @@ this.client_ = client; this.notifyClientOfDisplays(); - var device_number = (this.vr_displays_== null ? 0 : this.vr_displays_.length); + var device_number = (this.vrDisplays_== null ? 0 : this.vrDisplays_.length); return Promise.resolve({numberOfConnectedDevices: device_number}); } }
diff --git a/third_party/WebKit/Source/core/input/MouseEventManager.cpp b/third_party/WebKit/Source/core/input/MouseEventManager.cpp index d377ff2b..da2fdc0 100644 --- a/third_party/WebKit/Source/core/input/MouseEventManager.cpp +++ b/third_party/WebKit/Source/core/input/MouseEventManager.cpp
@@ -901,8 +901,7 @@ DragOperation operation) { if (dragState().m_dragSrc) { dragState().m_dragDataTransfer->setDestinationOperation(operation); - // For now we don't care if event handler cancels default behavior, since - // there is none. + // The return value is ignored because dragend is not cancelable. dispatchDragSrcEvent(EventTypeNames::dragend, event); } clearDragDataTransfer();
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_units.h b/third_party/WebKit/Source/core/layout/ng/ng_units.h index 235bf80..6c768d7 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_units.h +++ b/third_party/WebKit/Source/core/layout/ng/ng_units.h
@@ -348,8 +348,6 @@ LayoutUnit margin_end) const { DCHECK_GE(container_size, LayoutUnit()); DCHECK_GE(length, LayoutUnit()); - DCHECK_GE(margin_start, LayoutUnit()); - DCHECK_GE(margin_end, LayoutUnit()); if (position_matches) return position; else
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp index 6e8ab3d..93fc1fc5 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
@@ -422,8 +422,16 @@ localPaintingInfo.paintDirtyRect, cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, localPaintingInfo.subPixelAccumulation); - } else if (!collectPaintFragmentsForPaginatedFixedPosition( - paintingInfo, layerFragments)) { + } else if (isFixedPositionObjectInPagedMedia()) { + PaintLayerFragments singleFragment; + m_paintLayer.appendSingleFragmentIgnoringPagination( + singleFragment, localPaintingInfo.rootLayer, + localPaintingInfo.paintDirtyRect, cacheSlot, + IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, + localPaintingInfo.subPixelAccumulation); + repeatFixedPositionObjectInPages(singleFragment[0], paintingInfo, + layerFragments); + } else { m_paintLayer.collectFragments(layerFragments, localPaintingInfo.rootLayer, localPaintingInfo.paintDirtyRect, cacheSlot, IgnoreOverlayScrollbarSize, @@ -586,40 +594,42 @@ return false; } -bool PaintLayerPainter::collectPaintFragmentsForPaginatedFixedPosition( - const PaintLayerPaintingInfo& paintingInfo, - PaintLayerFragments& layerFragments) { +inline bool PaintLayerPainter::isFixedPositionObjectInPagedMedia() { LayoutObject* object = m_paintLayer.layoutObject(); LayoutView* view = object->view(); - bool isFixedPosObjectInPagedMedia = - object->style()->position() == FixedPosition && - object->container() == view && view->pageLogicalHeight(); + return object->styleRef().position() == FixedPosition && + object->container() == view && view->pageLogicalHeight() && + // TODO(crbug.com/619094): Figure out the correct behaviour for fixed + // position objects in paged media with vertical writing modes. + view->isHorizontalWritingMode(); +} - // TODO(crbug.com/619094): Figure out the correct behaviour for fixed position - // objects in paged media with vertical writing modes. - if (!isFixedPosObjectInPagedMedia || !view->isHorizontalWritingMode()) - return false; +void PaintLayerPainter::repeatFixedPositionObjectInPages( + const PaintLayerFragment& singleFragmentIgnoredPagination, + const PaintLayerPaintingInfo& paintingInfo, + PaintLayerFragments& layerFragments) { + DCHECK(isFixedPositionObjectInPagedMedia()); - // "For paged media, boxes with fixed positions are repeated on every page." - // https://www.w3.org/TR/2011/REC-CSS2-20110607/visuren.html#fixed-positioning + LayoutView* view = m_paintLayer.layoutObject()->view(); unsigned pages = ceilf(view->documentRect().height() / view->pageLogicalHeight()); - LayoutPoint paginationOffset; // The fixed position object is offset from the top of the page, so remove // any scroll offset. LayoutPoint offsetFromRoot; m_paintLayer.convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot); - paginationOffset -= offsetFromRoot - m_paintLayer.location(); + LayoutSize offsetAdjustment = m_paintLayer.location() - offsetFromRoot; + layerFragments.append(singleFragmentIgnoredPagination); + layerFragments[0].paginationOffset += offsetAdjustment; + layerFragments[0].layerBounds.move(offsetAdjustment); - for (unsigned i = 0; i < pages; i++) { - PaintLayerFragment fragment; - fragment.backgroundRect = paintingInfo.paintDirtyRect; - fragment.paginationOffset = paginationOffset; + LayoutPoint pageOffset(LayoutUnit(), view->pageLogicalHeight()); + for (unsigned i = 1; i < pages; i++) { + PaintLayerFragment fragment = layerFragments[i - 1]; + fragment.paginationOffset += pageOffset; + fragment.layerBounds.moveBy(pageOffset); layerFragments.append(fragment); - paginationOffset += LayoutPoint(LayoutUnit(), view->pageLogicalHeight()); } - return true; } PaintResult PaintLayerPainter::paintLayerWithTransform( @@ -637,48 +647,43 @@ // its parent. PaintLayer* parentLayer = m_paintLayer.parent(); - LayoutObject* object = m_paintLayer.layoutObject(); - LayoutView* view = object->view(); - bool isFixedPosObjectInPagedMedia = - object->style()->position() == FixedPosition && - object->container() == view && view->pageLogicalHeight(); PaintLayer* paginationLayer = m_paintLayer.enclosingPaginationLayer(); PaintLayerFragments layerFragments; - if (!collectPaintFragmentsForPaginatedFixedPosition(paintingInfo, - layerFragments)) { - if (paginationLayer) { - // FIXME: This is a mess. Look closely at this code and the code in Layer - // and fix any issues in it & refactor to make it obvious from code - // structure what it does and that it's correct. - ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) - ? UncachedClipRects - : PaintingClipRects; - ShouldRespectOverflowClipType respectOverflowClip = - shouldRespectOverflowClip(paintFlags, m_paintLayer.layoutObject()); - // Calculate the transformed bounding box in the current coordinate space, - // to figure out which fragmentainers (e.g. columns) we need to visit. - LayoutRect transformedExtent = PaintLayer::transparencyClipBox( - &m_paintLayer, paginationLayer, - PaintLayer::PaintingTransparencyClipBox, - PaintLayer::RootOfTransparencyClipBox, - paintingInfo.subPixelAccumulation, - paintingInfo.getGlobalPaintFlags()); - // FIXME: we don't check if paginationLayer is within - // paintingInfo.rootLayer - // here. - paginationLayer->collectFragments( - layerFragments, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, - cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, 0, - paintingInfo.subPixelAccumulation, &transformedExtent); - } else { - // We don't need to collect any fragments in the regular way here. We have - // already calculated a clip rectangle for the ancestry if it was needed, - // and clipping this layer is something that can be done further down the - // path, when the transform has been applied. - PaintLayerFragment fragment; - fragment.backgroundRect = paintingInfo.paintDirtyRect; + bool isFixedPositionObjectInPagedMedia = + this->isFixedPositionObjectInPagedMedia(); + if (!paginationLayer || isFixedPositionObjectInPagedMedia) { + // We don't need to collect any fragments in the regular way here. We have + // already calculated a clip rectangle for the ancestry if it was needed, + // and clipping this layer is something that can be done further down the + // path, when the transform has been applied. + PaintLayerFragment fragment; + fragment.backgroundRect = paintingInfo.paintDirtyRect; + if (isFixedPositionObjectInPagedMedia) + repeatFixedPositionObjectInPages(fragment, paintingInfo, layerFragments); + else layerFragments.append(fragment); - } + } else { + // FIXME: This is a mess. Look closely at this code and the code in Layer + // and fix any issues in it & refactor to make it obvious from code + // structure what it does and that it's correct. + ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) + ? UncachedClipRects + : PaintingClipRects; + ShouldRespectOverflowClipType respectOverflowClip = + shouldRespectOverflowClip(paintFlags, m_paintLayer.layoutObject()); + // Calculate the transformed bounding box in the current coordinate space, + // to figure out which fragmentainers (e.g. columns) we need to visit. + LayoutRect transformedExtent = PaintLayer::transparencyClipBox( + &m_paintLayer, paginationLayer, PaintLayer::PaintingTransparencyClipBox, + PaintLayer::RootOfTransparencyClipBox, + paintingInfo.subPixelAccumulation, paintingInfo.getGlobalPaintFlags()); + // FIXME: we don't check if paginationLayer is within + // paintingInfo.rootLayer + // here. + paginationLayer->collectFragments( + layerFragments, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, + cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, nullptr, + paintingInfo.subPixelAccumulation, &transformedExtent); } Optional<DisplayItemCacheSkipper> cacheSkipper; @@ -707,9 +712,9 @@ Optional<LayerClipRecorder> clipRecorder; if (parentLayer && !RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { ClipRect clipRectForFragment(ancestorBackgroundClipRect); - // A fixed-position object is repeated on every page, but if it is clipped - // by an ancestor layer then the repetitions are clipped out. - if (!isFixedPosObjectInPagedMedia) + // A fixed-position object is repeated on every page instead of paginated, + // so we should apply the original ancestor clip rect. + if (!isFixedPositionObjectInPagedMedia) clipRectForFragment.moveBy(fragment.paginationOffset); clipRectForFragment.intersect(fragment.backgroundRect); if (clipRectForFragment.isEmpty())
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.h b/third_party/WebKit/Source/core/paint/PaintLayerPainter.h index 3e9f349..2214bc5 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.h +++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.h
@@ -56,7 +56,15 @@ private: enum ClipState { HasNotClipped, HasClipped }; - bool collectPaintFragmentsForPaginatedFixedPosition( + inline bool isFixedPositionObjectInPagedMedia(); + + // "For paged media, boxes with fixed positions are repeated on every page." + // https://www.w3.org/TR/2011/REC-CSS2-20110607/visuren.html#fixed-positioning + // Repeats singleFragmentIgnoredPagination of the fixed-position object in + // each page, with paginationOffset and layerBounds adjusted for each page. + // TODO(wangxianzhu): Fold this into PaintLayer::collectFragments(). + void repeatFixedPositionObjectInPages( + const PaintLayerFragment& singleFragmentIgnoredPagination, const PaintLayerPaintingInfo&, PaintLayerFragments&);
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp index b01a6cd..d49e038 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -4,6 +4,7 @@ #include "core/paint/PaintPropertyTreeBuilder.h" +#include "core/dom/DOMNodeIds.h" #include "core/frame/FrameView.h" #include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" @@ -336,6 +337,16 @@ style.transformOriginZ()); } +namespace { + +CompositorElementId createDomNodeBasedCompositorElementId( + const LayoutObject& object) { + return createCompositorElementId(DOMNodeIds::idForNode(object.node()), + CompositorSubElementId::Primary); +} + +} // namespace + void PaintPropertyTreeBuilder::updateTransform( const LayoutObject& object, PaintPropertyTreeBuilderContext& context) { @@ -375,12 +386,17 @@ if (style.preserves3D() && !renderingContextId) renderingContextId = PtrHash<const LayoutObject>::hash(&object); + CompositorElementId compositorElementId = + style.hasCurrentTransformAnimation() + ? createDomNodeBasedCompositorElementId(object) + : CompositorElementId(); + auto& properties = object.getMutableForPainting().ensurePaintProperties(); context.forceSubtreeUpdate |= properties.updateTransform( context.current.transform, matrix, transformOrigin(box), context.current.shouldFlattenInheritedTransform, renderingContextId, - compositingReasons); + compositingReasons, compositorElementId); hasTransform = true; } } @@ -484,16 +500,23 @@ } CompositingReasons compositingReasons = - CompositingReasonFinder::requiresCompositingForEffectAnimation( - object.styleRef()); + CompositingReasonFinder::requiresCompositingForEffectAnimation(style); if (compositingReasons != CompositingReasonNone) effectNodeNeeded = true; + CompositorElementId compositorElementId = + (style.hasCurrentOpacityAnimation() || + style.hasCurrentFilterAnimation() || + style.hasCurrentBackdropFilterAnimation()) + ? createDomNodeBasedCompositorElementId(object) + : CompositorElementId(); + if (effectNodeNeeded) { auto& properties = object.getMutableForPainting().ensurePaintProperties(); context.forceSubtreeUpdate |= properties.updateEffect( context.currentEffect, context.current.transform, outputClip, - std::move(filter), opacity, blendMode, compositingReasons); + std::move(filter), opacity, blendMode, compositingReasons, + compositorElementId); } else { if (auto* properties = object.getMutableForPainting().paintProperties()) context.forceSubtreeUpdate |= properties->clearEffect();
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp index 46aa009..e7480ff 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -57,6 +57,11 @@ return object->paintProperties()->localBorderBoxProperties()->paintOffset; } +const ObjectPaintProperties* +PaintPropertyTreeBuilderTest::paintPropertiesForElement(const char* name) { + return document().getElementById(name)->layoutObject()->paintProperties(); +} + void PaintPropertyTreeBuilderTest::SetUp() { Settings::setMockScrollbarsEnabled(true); @@ -421,60 +426,24 @@ TEST_P(PaintPropertyTreeBuilderTest, TransformNodeWithActiveAnimationHasDirectCompositingReason) { - setBodyInnerHTML( - "<style>" - "@keyframes test {" - " 0% { transform: translate(1em, 1em) } " - " 100% { transform: translate(2em, 2em) } " - "} " - ".animate { " - " animation-name: test; " - " animation-duration: 1s " - "}" - "</style>" - "<div id='target' class='animate'></div>"); - Element* target = document().getElementById("target"); - const ObjectPaintProperties* properties = - target->layoutObject()->paintProperties(); - EXPECT_TRUE(properties->transform()->hasDirectCompositingReasons()); + loadTestData("transform-animation.html"); + EXPECT_TRUE(paintPropertiesForElement("target") + ->transform() + ->hasDirectCompositingReasons()); } -namespace { - -const char* kSimpleOpacityExampleHTML = - "<style>" - "div {" - " width: 100px;" - " height: 100px;" - " background-color: red;" - " animation-name: example;" - " animation-duration: 4s;" - "}" - "@keyframes example {" - " from { opacity: 0.0;}" - " to { opacity: 1.0;}" - "}" - "</style>" - "<div id='target'></div>"; - -} // namespace - TEST_P(PaintPropertyTreeBuilderTest, OpacityAnimationDoesNotCreateTransformNode) { - setBodyInnerHTML(kSimpleOpacityExampleHTML); - Element* target = document().getElementById("target"); - const ObjectPaintProperties* properties = - target->layoutObject()->paintProperties(); - EXPECT_EQ(nullptr, properties->transform()); + loadTestData("opacity-animation.html"); + EXPECT_EQ(nullptr, paintPropertiesForElement("target")->transform()); } TEST_P(PaintPropertyTreeBuilderTest, EffectNodeWithActiveAnimationHasDirectCompositingReason) { - setBodyInnerHTML(kSimpleOpacityExampleHTML); - Element* target = document().getElementById("target"); - const ObjectPaintProperties* properties = - target->layoutObject()->paintProperties(); - EXPECT_TRUE(properties->effect()->hasDirectCompositingReasons()); + loadTestData("opacity-animation.html"); + EXPECT_TRUE(paintPropertiesForElement("target") + ->effect() + ->hasDirectCompositingReasons()); } TEST_P(PaintPropertyTreeBuilderTest, WillChangeTransform) { @@ -3194,4 +3163,37 @@ ->propertyTreeState.clip()); } +TEST_P(PaintPropertyTreeBuilderTest, + TransformNodeNotAnimatedHasNoCompositorElementId) { + setBodyInnerHTML("<div id='target' style='transform: translateX(2em)'></div"); + const ObjectPaintProperties* properties = paintPropertiesForElement("target"); + EXPECT_TRUE(properties->transform()); + EXPECT_EQ(CompositorElementId(), + properties->transform()->compositorElementId()); +} + +TEST_P(PaintPropertyTreeBuilderTest, + EffectNodeNotAnimatedHasNoCompositorElementId) { + setBodyInnerHTML("<div id='target' style='opacity: 0.5'></div"); + const ObjectPaintProperties* properties = paintPropertiesForElement("target"); + EXPECT_TRUE(properties->effect()); + EXPECT_EQ(CompositorElementId(), properties->effect()->compositorElementId()); +} + +TEST_P(PaintPropertyTreeBuilderTest, + TransformNodeAnimatedHasCompositorElementId) { + loadTestData("transform-animation.html"); + const ObjectPaintProperties* properties = paintPropertiesForElement("target"); + EXPECT_TRUE(properties->transform()); + EXPECT_NE(CompositorElementId(), + properties->transform()->compositorElementId()); +} + +TEST_P(PaintPropertyTreeBuilderTest, EffectNodeAnimatedHasCompositorElementId) { + loadTestData("opacity-animation.html"); + const ObjectPaintProperties* properties = paintPropertiesForElement("target"); + EXPECT_TRUE(properties->effect()); + EXPECT_NE(CompositorElementId(), properties->effect()->compositorElementId()); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.h b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.h index 1f936e7..6c023f6 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.h +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.h
@@ -40,6 +40,8 @@ // ObjectPaintProperties::localBorderBoxProperties(). LayoutPoint paintOffset(const LayoutObject*); + const ObjectPaintProperties* paintPropertiesForElement(const char* name); + private: void SetUp() override; void TearDown() override;
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeUpdateTests.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeUpdateTests.cpp index 4401e5f..a2a0a83 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeUpdateTests.cpp +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeUpdateTests.cpp
@@ -445,18 +445,7 @@ TEST_P(PaintPropertyTreeUpdateTest, TransformNodeWithAnimationLosesNodeWhenAnimationRemoved) { - setBodyInnerHTML( - "<style>" - "@keyframes test {" - " 0% { transform: translate(1em, 1em) } " - " 100% { transform: translate(2em, 2em) } " - "} " - ".animate { " - " animation-name: test; " - " animation-duration: 1s " - "}" - "</style>" - "<div id='target' class='animate'></div>"); + loadTestData("transform-animation.html"); Element* target = document().getElementById("target"); const ObjectPaintProperties* properties = target->layoutObject()->paintProperties(); @@ -470,23 +459,7 @@ TEST_P(PaintPropertyTreeUpdateTest, EffectNodeWithAnimationLosesNodeWhenAnimationRemoved) { - setBodyInnerHTML( - "<style>" - "div {" - " width: 100px;" - " height: 100px;" - " background-color: red;" - "} " - ".animate {" - " animation-name: test;" - " animation-duration: 4s;" - "}" - "@keyframes test {" - " from { opacity: 0.0;}" - " to { opacity: 1.0;}" - "}" - "</style>" - "<div id='target' class='animate'></div>"); + loadTestData("opacity-animation.html"); Element* target = document().getElementById("target"); const ObjectPaintProperties* properties = target->layoutObject()->paintProperties(); @@ -498,6 +471,43 @@ EXPECT_EQ(nullptr, properties->effect()); } +TEST_P(PaintPropertyTreeUpdateTest, + TransformNodeLosesCompositorElementIdWhenAnimationRemoved) { + loadTestData("transform-animation.html"); + + Element* target = document().getElementById("target"); + target->setAttribute(HTMLNames::styleAttr, "transform: translateX(2em)"); + document().view()->updateAllLifecyclePhases(); + + const ObjectPaintProperties* properties = + target->layoutObject()->paintProperties(); + EXPECT_NE(CompositorElementId(), + properties->transform()->compositorElementId()); + + // Remove the animation but keep the transform on the element. + target->removeAttribute(HTMLNames::classAttr); + document().view()->updateAllLifecyclePhases(); + EXPECT_EQ(CompositorElementId(), + properties->transform()->compositorElementId()); +} + +TEST_P(PaintPropertyTreeUpdateTest, + EffectNodeLosesCompositorElementIdWhenAnimationRemoved) { + loadTestData("opacity-animation.html"); + + Element* target = document().getElementById("target"); + target->setAttribute(HTMLNames::styleAttr, "opacity: 0.2"); + document().view()->updateAllLifecyclePhases(); + + const ObjectPaintProperties* properties = + target->layoutObject()->paintProperties(); + EXPECT_NE(CompositorElementId(), properties->effect()->compositorElementId()); + + target->removeAttribute(HTMLNames::classAttr); + document().view()->updateAllLifecyclePhases(); + EXPECT_EQ(CompositorElementId(), properties->effect()->compositorElementId()); +} + TEST_P(PaintPropertyTreeUpdateTest, PerspectiveOriginUpdatesOnSizeChanges) { setBodyInnerHTML( "<style>"
diff --git a/third_party/WebKit/Source/core/paint/test_data/opacity-animation.html b/third_party/WebKit/Source/core/paint/test_data/opacity-animation.html new file mode 100644 index 0000000..0cfdd94 --- /dev/null +++ b/third_party/WebKit/Source/core/paint/test_data/opacity-animation.html
@@ -0,0 +1,17 @@ +<!DOCTYPE html> +<style> +div { + width: 100px; + height: 100px; + background-color: red; +} +.animate { + animation-name: test; + animation-duration: 4s; +} +@keyframes test { + from { opacity: 0.0;} + to { opacity: 1.0;} +} +</style> +<div id="target" class="animate"></div>;
diff --git a/third_party/WebKit/Source/core/paint/test_data/transform-animation.html b/third_party/WebKit/Source/core/paint/test_data/transform-animation.html new file mode 100644 index 0000000..600e840 --- /dev/null +++ b/third_party/WebKit/Source/core/paint/test_data/transform-animation.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<style> +@keyframes test { + 0% { transform: translate(1em, 1em) } + 100% { transform: translate(2em, 2em) } +} + +.animate { + animation-name: test; + animation-duration: 1s; +} +</style> +<div id="target" class="animate"></div>;
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js index ded653baa..7336342 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
@@ -1241,7 +1241,7 @@ return; if (this.propertiesTreeOutline.element.shadowRoot.firstChild && - this.propertiesTreeOutline.element.shadowRoot.firstChild.isComponentSelectionCollapsed()) + !this.propertiesTreeOutline.element.shadowRoot.firstChild.isComponentSelectionCollapsed()) return; if (this._checkWillCancelEditing())
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/ListControl.js b/third_party/WebKit/Source/devtools/front_end/ui/ListControl.js index 6635829..b80e963e 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/ListControl.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/ListControl.js
@@ -389,7 +389,7 @@ oldElement = this._itemToElement.get(oldItem) || null; this._selectedIndex = index; var newItem = this._selectedIndex !== -1 ? this._items[this._selectedIndex] : null; - var newElement = this._itemToElement.get(newItem) || null; + var newElement = this._selectedIndex !== -1 ? this._elementAtIndex(index) : null; this._delegate.selectedItemChanged(oldItem, newItem, /** @type {?Element} */ (oldElement), newElement); }
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js b/third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js index ee250df..38c08d6 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/SuggestBox.js
@@ -67,11 +67,6 @@ this._element.classList.add('suggest-box'); this._container.appendChild(this._element); this._element.addEventListener('mousedown', this._onBoxMouseDown.bind(this), true); - this._detailsPopup = this._container.createChild('div', 'suggest-box details-popup monospace'); - this._detailsPopup.classList.add('hidden'); - this._asyncDetailsCallback = null; - /** @type {!Map<!UI.SuggestBox.Suggestion, !Promise<{detail: string, description: string}>>} */ - this._asyncDetailsPromises = new Map(); this._userInteracted = false; this._captureEnter = captureEnter; this._viewportWidth = '100vw'; @@ -295,11 +290,6 @@ toElement.classList.add('selected', 'force-white-icons'); if (!to) return; - this._detailsPopup.classList.add('hidden'); - this._asyncDetails(to).then(details => { - if (this._list.selectedItem() === to) - this._showDetailsPopup(details); - }); this._applySuggestion(true); } @@ -315,30 +305,6 @@ } /** - * @param {!UI.SuggestBox.Suggestion} item - * @return {!Promise<?{detail: string, description: string}>} - */ - _asyncDetails(item) { - if (!this._asyncDetailsCallback) - return Promise.resolve(/** @type {?{description: string, detail: string}} */ (null)); - if (!this._asyncDetailsPromises.has(item)) - this._asyncDetailsPromises.set(item, this._asyncDetailsCallback(item)); - return /** @type {!Promise<?{detail: string, description: string}>} */ (this._asyncDetailsPromises.get(item)); - } - - /** - * @param {?{detail: string, description: string}} details - */ - _showDetailsPopup(details) { - this._detailsPopup.removeChildren(); - if (!details) - return; - this._detailsPopup.createChild('section', 'detail').createTextChild(details.detail); - this._detailsPopup.createChild('section', 'description').createTextChild(details.description); - this._detailsPopup.classList.remove('hidden'); - } - - /** * @param {!UI.SuggestBox.Suggestions} completions * @param {boolean} canShowForSingleItem * @param {string} userEnteredText @@ -364,22 +330,10 @@ * @param {boolean} selectHighestPriority * @param {boolean} canShowForSingleItem * @param {string} userEnteredText - * @param {function(number): !Promise<{detail:string, description:string}>=} asyncDetails */ - updateSuggestions( - anchorBox, - completions, - selectHighestPriority, - canShowForSingleItem, - userEnteredText, - asyncDetails) { + updateSuggestions(anchorBox, completions, selectHighestPriority, canShowForSingleItem, userEnteredText) { delete this._onlyCompletion; if (this._canShowBox(completions, canShowForSingleItem, userEnteredText)) { - this._asyncDetailsPromises.clear(); - if (asyncDetails) - this._asyncDetailsCallback = item => asyncDetails(completions.indexOf(item)); - else - this._asyncDetailsCallback = null; this._userEnteredText = userEnteredText; this._show();
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/suggestBox.css b/third_party/WebKit/Source/devtools/front_end/ui/suggestBox.css index 7d46270..fc0359d 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/suggestBox.css +++ b/third_party/WebKit/Source/devtools/front_end/ui/suggestBox.css
@@ -123,16 +123,3 @@ .suggest-box .suggest-box-content-item:hover:not(.selected) { background-color: rgba(56, 121, 217, 0.1); } - -.suggest-box .details-popup { - padding: 17px; - pointer-events: auto; - margin-left: 3px; - max-width: 750px; - word-wrap: normal; -} - -.suggest-box .details-popup .description { - margin-top: 22px; - color: #808080; -}
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothAttributeInstanceMap.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothAttributeInstanceMap.cpp index 63d3283..14a9734 100644 --- a/third_party/WebKit/Source/modules/bluetooth/BluetoothAttributeInstanceMap.cpp +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothAttributeInstanceMap.cpp
@@ -16,7 +16,7 @@ : m_device(device) {} BluetoothRemoteGATTService* -BluetoothAttributeInstanceMap::getOrCreateBluetoothRemoteGATTService( +BluetoothAttributeInstanceMap::getOrCreateRemoteGATTService( const String& serviceInstanceId, const String& uuid, bool isPrimary, @@ -39,7 +39,7 @@ } BluetoothRemoteGATTCharacteristic* -BluetoothAttributeInstanceMap::getOrCreateBluetoothRemoteGATTCharacteristic( +BluetoothAttributeInstanceMap::getOrCreateRemoteGATTCharacteristic( ExecutionContext* context, const String& characteristicInstanceId, const String& serviceInstanceId,
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothAttributeInstanceMap.h b/third_party/WebKit/Source/modules/bluetooth/BluetoothAttributeInstanceMap.h index 50ba595..0fb529c 100644 --- a/third_party/WebKit/Source/modules/bluetooth/BluetoothAttributeInstanceMap.h +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothAttributeInstanceMap.h
@@ -29,7 +29,7 @@ // no service with the same instance id and adds it to the map. // Otherwise returns the BluetoothRemoteGATTService object already // in the map. - BluetoothRemoteGATTService* getOrCreateBluetoothRemoteGATTService( + BluetoothRemoteGATTService* getOrCreateRemoteGATTService( const String& serviceInstanceId, const String& uuid, bool isPrimary, @@ -43,8 +43,7 @@ // characteristic with the same instance id and adds it to the map. // Otherwise returns the BluetoothRemoteGATTCharacteristic object already in // the map. - BluetoothRemoteGATTCharacteristic* - getOrCreateBluetoothRemoteGATTCharacteristic( + BluetoothRemoteGATTCharacteristic* getOrCreateRemoteGATTCharacteristic( ExecutionContext*, const String& characteristicInstanceId, const String& serviceInstanceId,
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothDevice.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothDevice.cpp index 8ea588a4..1b0fb018 100644 --- a/third_party/WebKit/Source/modules/bluetooth/BluetoothDevice.cpp +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothDevice.cpp
@@ -46,13 +46,12 @@ return result; } -BluetoothRemoteGATTService* -BluetoothDevice::getOrCreateBluetoothRemoteGATTService( +BluetoothRemoteGATTService* BluetoothDevice::getOrCreateRemoteGATTService( const String& serviceInstanceId, const String& uuid, bool isPrimary, const String& deviceInstanceId) { - return m_attributeInstanceMap->getOrCreateBluetoothRemoteGATTService( + return m_attributeInstanceMap->getOrCreateRemoteGATTService( serviceInstanceId, uuid, isPrimary, deviceInstanceId); } @@ -61,14 +60,14 @@ } BluetoothRemoteGATTCharacteristic* -BluetoothDevice::getOrCreateBluetoothRemoteGATTCharacteristic( +BluetoothDevice::getOrCreateRemoteGATTCharacteristic( ExecutionContext* context, const String& characteristicInstanceId, const String& serviceInstanceId, const String& uuid, uint32_t characteristicProperties, BluetoothRemoteGATTService* service) { - return m_attributeInstanceMap->getOrCreateBluetoothRemoteGATTCharacteristic( + return m_attributeInstanceMap->getOrCreateRemoteGATTCharacteristic( context, characteristicInstanceId, serviceInstanceId, uuid, characteristicProperties, service); }
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothDevice.h b/third_party/WebKit/Source/modules/bluetooth/BluetoothDevice.h index 7cae3ba..61f97528 100644 --- a/third_party/WebKit/Source/modules/bluetooth/BluetoothDevice.h +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothDevice.h
@@ -50,15 +50,14 @@ static mojom::blink::WebBluetoothDeviceIdPtr createMojoDeviceId( const String& deviceId); - BluetoothRemoteGATTService* getOrCreateBluetoothRemoteGATTService( + BluetoothRemoteGATTService* getOrCreateRemoteGATTService( const String& serviceInstanceId, const String& uuid, bool isPrimary, const String& deviceInstanceId); bool isValidService(const String& serviceInstanceId); - BluetoothRemoteGATTCharacteristic* - getOrCreateBluetoothRemoteGATTCharacteristic( + BluetoothRemoteGATTCharacteristic* getOrCreateRemoteGATTCharacteristic( ExecutionContext*, const String& characteristicInstanceId, const String& serviceInstanceId,
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.cpp index 0b5bf816..5ac6a05 100644 --- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.cpp +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.cpp
@@ -123,7 +123,7 @@ if (quantity == mojom::blink::WebBluetoothGATTQueryQuantity::SINGLE) { DCHECK_EQ(1u, services->size()); - resolver->resolve(m_device->getOrCreateBluetoothRemoteGATTService( + resolver->resolve(m_device->getOrCreateRemoteGATTService( services.value()[0]->instance_id, services.value()[0]->uuid, true /* isPrimary */, device()->id())); return; @@ -133,7 +133,7 @@ gattServices.reserveInitialCapacity(services->size()); for (const auto& service : services.value()) { - gattServices.append(m_device->getOrCreateBluetoothRemoteGATTService( + gattServices.append(m_device->getOrCreateRemoteGATTService( service->instance_id, service->uuid, true /* isPrimary */, device()->id())); }
diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTService.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTService.cpp index 729c1a6..d73dd6b 100644 --- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTService.cpp +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTService.cpp
@@ -73,7 +73,7 @@ if (quantity == mojom::blink::WebBluetoothGATTQueryQuantity::SINGLE) { DCHECK_EQ(1u, characteristics->size()); - resolver->resolve(device()->getOrCreateBluetoothRemoteGATTCharacteristic( + resolver->resolve(device()->getOrCreateRemoteGATTCharacteristic( resolver->getExecutionContext(), characteristics.value()[0]->instance_id, serviceInstanceId, characteristics.value()[0]->uuid, @@ -84,11 +84,10 @@ HeapVector<Member<BluetoothRemoteGATTCharacteristic>> gattCharacteristics; gattCharacteristics.reserveInitialCapacity(characteristics->size()); for (const auto& characteristic : characteristics.value()) { - gattCharacteristics.append( - device()->getOrCreateBluetoothRemoteGATTCharacteristic( - resolver->getExecutionContext(), characteristic->instance_id, - serviceInstanceId, characteristic->uuid, - characteristic->properties, this)); + gattCharacteristics.append(device()->getOrCreateRemoteGATTCharacteristic( + resolver->getExecutionContext(), characteristic->instance_id, + serviceInstanceId, characteristic->uuid, characteristic->properties, + this)); } resolver->resolve(gattCharacteristics); } else {
diff --git a/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.cpp b/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.cpp index 85a7293..38d423b 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.cpp
@@ -26,11 +26,12 @@ String EffectPaintPropertyNode::toString() const { return String::format( "parent=%p localTransformSpace=%p outputClip=%p opacity=%f filter=%s " - "blendMode=%s directCompositingReasons=%s", + "blendMode=%s directCompositingReasons=%s compositorElementId=(%d, %d)", m_parent.get(), m_localTransformSpace.get(), m_outputClip.get(), m_opacity, m_filter.toString().ascii().data(), SkBlendMode_Name(m_blendMode), - compositingReasonsAsString(m_directCompositingReasons).ascii().data()); + compositingReasonsAsString(m_directCompositingReasons).ascii().data(), + m_compositorElementId.primaryId, m_compositorElementId.secondaryId); } } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h b/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h index ec1a562..2dd0c71 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h +++ b/third_party/WebKit/Source/platform/graphics/paint/EffectPaintPropertyNode.h
@@ -7,6 +7,7 @@ #include "cc/layers/layer.h" #include "platform/PlatformExport.h" +#include "platform/graphics/CompositorElementId.h" #include "platform/graphics/CompositorFilterOperations.h" #include "platform/graphics/paint/ClipPaintPropertyNode.h" #include "platform/graphics/paint/TransformPaintPropertyNode.h" @@ -36,11 +37,12 @@ CompositorFilterOperations filter, float opacity, SkBlendMode blendMode, - CompositingReasons directCompositingReasons = CompositingReasonNone) { + CompositingReasons directCompositingReasons = CompositingReasonNone, + const CompositorElementId& compositorElementId = CompositorElementId()) { return adoptRef(new EffectPaintPropertyNode( std::move(parent), std::move(localTransformSpace), std::move(outputClip), std::move(filter), opacity, blendMode, - directCompositingReasons)); + directCompositingReasons, compositorElementId)); } void update( @@ -50,7 +52,8 @@ CompositorFilterOperations filter, float opacity, SkBlendMode blendMode, - CompositingReasons directCompositingReasons = CompositingReasonNone) { + CompositingReasons directCompositingReasons = CompositingReasonNone, + CompositorElementId compositorElementId = CompositorElementId()) { DCHECK(!isRoot()); DCHECK(parent != this); m_parent = parent; @@ -60,6 +63,7 @@ m_opacity = opacity; m_blendMode = blendMode; m_directCompositingReasons = directCompositingReasons; + m_compositorElementId = compositorElementId; } const TransformPaintPropertyNode* localTransformSpace() const { @@ -83,7 +87,7 @@ PassRefPtr<EffectPaintPropertyNode> clone() const { return adoptRef(new EffectPaintPropertyNode( m_parent, m_localTransformSpace, m_outputClip, m_filter, m_opacity, - m_blendMode, m_directCompositingReasons)); + m_blendMode, m_directCompositingReasons, m_compositorElementId)); } // The equality operator is used by FindPropertiesNeedingUpdate.h for checking @@ -95,7 +99,8 @@ m_outputClip == o.m_outputClip && m_filter.equalsIgnoringReferenceFilters(o.m_filter) && m_opacity == o.m_opacity && m_blendMode == o.m_blendMode && - m_directCompositingReasons == o.m_directCompositingReasons; + m_directCompositingReasons == o.m_directCompositingReasons && + m_compositorElementId == o.m_compositorElementId; } #endif @@ -105,6 +110,10 @@ return m_directCompositingReasons != CompositingReasonNone; } + const CompositorElementId& compositorElementId() const { + return m_compositorElementId; + } + private: EffectPaintPropertyNode( PassRefPtr<const EffectPaintPropertyNode> parent, @@ -113,14 +122,16 @@ CompositorFilterOperations filter, float opacity, SkBlendMode blendMode, - CompositingReasons directCompositingReasons) + CompositingReasons directCompositingReasons, + CompositorElementId compositorElementId) : m_parent(parent), m_localTransformSpace(localTransformSpace), m_outputClip(outputClip), m_filter(std::move(filter)), m_opacity(opacity), m_blendMode(blendMode), - m_directCompositingReasons(directCompositingReasons) {} + m_directCompositingReasons(directCompositingReasons), + m_compositorElementId(compositorElementId) {} RefPtr<const EffectPaintPropertyNode> m_parent; // The local transform space serves two purposes: @@ -149,6 +160,7 @@ mutable scoped_refptr<cc::Layer> m_dummyLayer; CompositingReasons m_directCompositingReasons; + CompositorElementId m_compositorElementId; }; // Redeclared here to avoid ODR issues.
diff --git a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.cpp b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.cpp index e7162129..70cbe4c0 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.cpp
@@ -16,11 +16,14 @@ String TransformPaintPropertyNode::toString() const { return String::format( "parent=%p transform=%s origin=%s flattensInheritedTransform=%s " - "renderContextID=%x directCompositingReasons=%s", + "renderingContextId=%x directCompositingReasons=%s " + "compositorElementId=(%d, " + "%d)", m_parent.get(), m_matrix.toString().ascii().data(), m_origin.toString().ascii().data(), m_flattensInheritedTransform ? "yes" : "no", m_renderingContextId, - compositingReasonsAsString(m_directCompositingReasons).ascii().data()); + compositingReasonsAsString(m_directCompositingReasons).ascii().data(), + m_compositorElementId.primaryId, m_compositorElementId.secondaryId); } } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h index be4c3667..d159197 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h +++ b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h
@@ -8,6 +8,7 @@ #include "platform/PlatformExport.h" #include "platform/geometry/FloatPoint3D.h" #include "platform/graphics/CompositingReasons.h" +#include "platform/graphics/CompositorElementId.h" #include "platform/transforms/TransformationMatrix.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" @@ -34,10 +35,11 @@ const FloatPoint3D& origin, bool flattensInheritedTransform = false, unsigned renderingContextId = 0, - CompositingReasons directCompositingReasons = CompositingReasonNone) { + CompositingReasons directCompositingReasons = CompositingReasonNone, + const CompositorElementId& compositorElementId = CompositorElementId()) { return adoptRef(new TransformPaintPropertyNode( std::move(parent), matrix, origin, flattensInheritedTransform, - renderingContextId, directCompositingReasons)); + renderingContextId, directCompositingReasons, compositorElementId)); } void update( @@ -46,7 +48,8 @@ const FloatPoint3D& origin, bool flattensInheritedTransform = false, unsigned renderingContextId = 0, - CompositingReasons directCompositingReasons = CompositingReasonNone) { + CompositingReasons directCompositingReasons = CompositingReasonNone, + CompositorElementId compositorElementId = CompositorElementId()) { DCHECK(!isRoot()); DCHECK(parent != this); m_parent = parent; @@ -55,6 +58,7 @@ m_flattensInheritedTransform = flattensInheritedTransform; m_renderingContextId = renderingContextId; m_directCompositingReasons = directCompositingReasons; + m_compositorElementId = compositorElementId; } const TransformationMatrix& matrix() const { return m_matrix; } @@ -76,6 +80,10 @@ return m_directCompositingReasons != CompositingReasonNone; } + const CompositorElementId& compositorElementId() const { + return m_compositorElementId; + } + // Content whose transform nodes have a common rendering context ID are 3D // sorted. If this is 0, content will not be 3D sorted. unsigned renderingContextId() const { return m_renderingContextId; } @@ -87,7 +95,8 @@ PassRefPtr<TransformPaintPropertyNode> clone() const { return adoptRef(new TransformPaintPropertyNode( m_parent, m_matrix, m_origin, m_flattensInheritedTransform, - m_renderingContextId, m_directCompositingReasons)); + m_renderingContextId, m_directCompositingReasons, + m_compositorElementId)); } // The equality operator is used by FindPropertiesNeedingUpdate.h for checking @@ -97,7 +106,8 @@ m_origin == o.m_origin && m_flattensInheritedTransform == o.m_flattensInheritedTransform && m_renderingContextId == o.m_renderingContextId && - m_directCompositingReasons == o.m_directCompositingReasons; + m_directCompositingReasons == o.m_directCompositingReasons && + m_compositorElementId == o.m_compositorElementId; } #endif @@ -110,13 +120,15 @@ const FloatPoint3D& origin, bool flattensInheritedTransform, unsigned renderingContextId, - CompositingReasons directCompositingReasons) + CompositingReasons directCompositingReasons, + CompositorElementId compositorElementId) : m_parent(parent), m_matrix(matrix), m_origin(origin), m_flattensInheritedTransform(flattensInheritedTransform), m_renderingContextId(renderingContextId), - m_directCompositingReasons(directCompositingReasons) {} + m_directCompositingReasons(directCompositingReasons), + m_compositorElementId(compositorElementId) {} RefPtr<const TransformPaintPropertyNode> m_parent; TransformationMatrix m_matrix; @@ -124,6 +136,7 @@ bool m_flattensInheritedTransform; unsigned m_renderingContextId; CompositingReasons m_directCompositingReasons; + CompositorElementId m_compositorElementId; }; // Redeclared here to avoid ODR issues.
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baseline_optimizer.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baseline_optimizer.py index ee18001..d67aef8d 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baseline_optimizer.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/baseline_optimizer.py
@@ -35,17 +35,6 @@ _log = logging.getLogger(__name__) -# FIXME: Should this function be somewhere more general? -def _invert_dictionary(dictionary): - inverted_dictionary = {} - for key, value in dictionary.items(): - if inverted_dictionary.get(value): - inverted_dictionary[value].append(key) - else: - inverted_dictionary[value] = [key] - return inverted_dictionary - - class BaselineOptimizer(object): ROOT_LAYOUT_TESTS_DIRECTORY = 'LayoutTests'
diff --git a/third_party/closure_compiler/externs/quick_unlock_private.js b/third_party/closure_compiler/externs/quick_unlock_private.js index aa6f6d2b..2b97520 100644 --- a/third_party/closure_compiler/externs/quick_unlock_private.js +++ b/third_party/closure_compiler/externs/quick_unlock_private.js
@@ -25,6 +25,35 @@ }; /** + * @enum {string} + * @see https://developer.chrome.com/extensions/quickUnlockPrivate#type-CredentialProblem + */ +chrome.quickUnlockPrivate.CredentialProblem = { + TOO_SHORT: 'TOO_SHORT', + TOO_LONG: 'TOO_LONG', + TOO_WEAK: 'TOO_WEAK', + CONTAINS_NONDIGIT: 'CONTAINS_NONDIGIT', +}; + +/** + * @typedef {{ + * errors: !Array<!chrome.quickUnlockPrivate.CredentialProblem>, + * warnings: !Array<!chrome.quickUnlockPrivate.CredentialProblem> + * }} + * @see https://developer.chrome.com/extensions/quickUnlockPrivate#type-CredentialCheck + */ +chrome.quickUnlockPrivate.CredentialCheck; + +/** + * @typedef {{ + * minLength: number, + * maxLength: number + * }} + * @see https://developer.chrome.com/extensions/quickUnlockPrivate#type-CredentialRequirements + */ +chrome.quickUnlockPrivate.CredentialRequirements; + +/** * Returns the set of quick unlock modes that are available for the user to use. * Some quick unlock modes may be disabled by policy. * @param {function(!Array<!chrome.quickUnlockPrivate.QuickUnlockMode>):void} @@ -43,6 +72,30 @@ chrome.quickUnlockPrivate.getActiveModes = function(onComplete) {}; /** + * Checks if the given credential can be used for the given unlock mode. + * Enterprise policy can change credential requirements. + * @param {!chrome.quickUnlockPrivate.QuickUnlockMode} mode The quick unlock + * mode that is used. + * @param {string} credential The given credential. + * @param {function(!chrome.quickUnlockPrivate.CredentialCheck):void} onComplete + * Called with a list of warnings and errors the given |credential| has + * (or an empty list if there are none). + * @see https://developer.chrome.com/extensions/quickUnlockPrivate#method-checkCredential + */ +chrome.quickUnlockPrivate.checkCredential = function(mode, credential, onComplete) {}; + +/** + * Gets the credential requirements for the given unlock mode. + * @param {!chrome.quickUnlockPrivate.QuickUnlockMode} mode The quick unlock + * mode that is used. + * @param {function(!chrome.quickUnlockPrivate.CredentialRequirements):void} + * onComplete Called with the credential requirements of the given + * |mode|. + * @see https://developer.chrome.com/extensions/quickUnlockPrivate#method-getCredentialRequirements + */ +chrome.quickUnlockPrivate.getCredentialRequirements = function(mode, onComplete) {}; + +/** * Update the set of quick unlock modes that are currently active/enabled. * @param {string} accountPassword The password associated with the account * (e.g. the GAIA password). This is required to change the quick unlock
diff --git a/third_party/closure_compiler/interfaces/quick_unlock_private_interface.js b/third_party/closure_compiler/interfaces/quick_unlock_private_interface.js index 5fe9756e..93319196 100644 --- a/third_party/closure_compiler/interfaces/quick_unlock_private_interface.js +++ b/third_party/closure_compiler/interfaces/quick_unlock_private_interface.js
@@ -32,6 +32,30 @@ getActiveModes: assertNotReached, /** + * Checks if the given credential can be used for the given unlock mode. + * Enterprise policy can change credential requirements. + * @param {!chrome.quickUnlockPrivate.QuickUnlockMode} mode The quick unlock + * mode that is used. + * @param {string} credential The given credential. + * @param {function(!chrome.quickUnlockPrivate.CredentialCheck):void} + * onComplete Called with a list of warnings and errors the given + * |credential| has (or an empty list if there are none). + * @see https://developer.chrome.com/extensions/quickUnlockPrivate#method-checkCredential + */ + checkCredential: assertNotReached, + + /** + * Gets the credential requirements for the given unlock mode. + * @param {!chrome.quickUnlockPrivate.QuickUnlockMode} mode The quick unlock + * mode that is used. + * @param {function(!chrome.quickUnlockPrivate.CredentialRequirements):void} + * onComplete Called with the credential requirements of the given + * |mode|. + * @see https://developer.chrome.com/extensions/quickUnlockPrivate#method-getCredentialRequirements + */ + getCredentialRequirements: assertNotReached, + + /** * Update the set of quick unlock modes that are currently active/enabled. * @param {string} accountPassword The password associated with the account * (e.g. the GAIA password). This is required to change the quick unlock
diff --git a/third_party/retrolambda/LICENSE.txt b/third_party/retrolambda/LICENSE similarity index 100% rename from third_party/retrolambda/LICENSE.txt rename to third_party/retrolambda/LICENSE
diff --git a/tools/gn/docs/reference.md b/tools/gn/docs/reference.md index b62abbd..034a112 100644 --- a/tools/gn/docs/reference.md +++ b/tools/gn/docs/reference.md
@@ -3967,7 +3967,7 @@ This addition happens in a second phase once a target and all of its dependencies have been resolved. Therefore, a target will not see these force-added configs in their "configs" variable while the script is running, - and then can not be removed. As a result, this capability should generally + and they can not be removed. As a result, this capability should generally only be used to add defines and include directories necessary to compile a target's headers. @@ -5434,7 +5434,7 @@ This addition happens in a second phase once a target and all of its dependencies have been resolved. Therefore, a target will not see these force-added configs in their "configs" variable while the script is running, - and then can not be removed. As a result, this capability should generally + and they can not be removed. As a result, this capability should generally only be used to add defines and include directories necessary to compile a target's headers.
diff --git a/tools/gn/variables.cc b/tools/gn/variables.cc index d387baeb..3b60c90 100644 --- a/tools/gn/variables.cc +++ b/tools/gn/variables.cc
@@ -416,7 +416,7 @@ This addition happens in a second phase once a target and all of its dependencies have been resolved. Therefore, a target will not see these force-added configs in their "configs" variable while the script is running, - and then can not be removed. As a result, this capability should generally + and they can not be removed. As a result, this capability should generally only be used to add defines and include directories necessary to compile a target's headers. @@ -1575,7 +1575,7 @@ This addition happens in a second phase once a target and all of its dependencies have been resolved. Therefore, a target will not see these force-added configs in their "configs" variable while the script is running, - and then can not be removed. As a result, this capability should generally + and they can not be removed. As a result, this capability should generally only be used to add defines and include directories necessary to compile a target's headers.
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index e2aa4a44..72d028f 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -13162,6 +13162,16 @@ </description> </action> +<action name="PhysicalWeb.Prefs.FromOmnibox"> + <owner>cco3@chromium.org</owner> + <owner>mattreynolds@chromium.org</owner> + <owner>mmocny@chromium.org</owner> + <description> + The user tapped the Physical Web logo in an omnibox suggestion and navigated + to the Physical Web preferences page. iOS only. + </description> +</action> + <action name="PhysicalWeb.Prefs.LocationDenied"> <owner>cco3@chromium.org</owner> <owner>mattreynolds@chromium.org</owner>
diff --git a/ui/ozone/platform/drm/common/drm_util.cc b/ui/ozone/platform/drm/common/drm_util.cc index 1de26fd7..8deaa6e 100644 --- a/ui/ozone/platform/drm/common/drm_util.cc +++ b/ui/ozone/platform/drm/common/drm_util.cc
@@ -14,26 +14,6 @@ #include "ui/display/util/edid_parser.h" -#if !defined(DRM_MODE_CONNECTOR_DSI) -#define DRM_MODE_CONNECTOR_DSI 16 -#endif - -#if !defined(DRM_CAP_CURSOR_WIDTH) -#define DRM_CAP_CURSOR_WIDTH 0x8 -#endif - -#if !defined(DRM_CAP_CURSOR_HEIGHT) -#define DRM_CAP_CURSOR_HEIGHT 0x9 -#endif - -#if !defined(DRM_FORMAT_R8) -// TODO(dshwang): after most linux and libdrm has this definition, remove it. -#define DRM_FORMAT_R8 fourcc_code('R', '8', ' ', ' ') -#endif -#if !defined(DRM_FORMAT_GR88) -// TODO(dshwang): after most linux and libdrm has this definition, remove it. -#define DRM_FORMAT_GR88 fourcc_code('G', 'R', '8', '8') -#endif #if !defined(DRM_FORMAT_YV12) // TODO(dcastagna): after libdrm has this definition, remove it. #define DRM_FORMAT_YV12 fourcc_code('Y', 'V', '1', '2')
diff --git a/ui/views/controls/table/table_view.cc b/ui/views/controls/table/table_view.cc index 271d2d9..ef65a29 100644 --- a/ui/views/controls/table/table_view.cc +++ b/ui/views/controls/table/table_view.cc
@@ -135,7 +135,7 @@ table_type_(table_type), single_selection_(single_selection), select_on_remove_(true), - table_view_observer_(NULL), + observer_(NULL), row_height_(font_list_.GetHeight() + kTextVerticalPadding * 2), last_parent_width_(0), layout_width_(0), @@ -193,10 +193,6 @@ return model_ ? model_->RowCount() : 0; } -int TableView::SelectedRowCount() { - return static_cast<int>(selection_model_.size()); -} - void TableView::Select(int model_row) { if (!model_) return; @@ -205,7 +201,7 @@ } int TableView::FirstSelectedRow() { - return SelectedRowCount() == 0 ? -1 : selection_model_.selected_indices()[0]; + return selection_model_.empty() ? -1 : selection_model_.selected_indices()[0]; } void TableView::SetColumnVisibility(int id, bool is_visible) { @@ -392,8 +388,8 @@ default: break; } - if (table_view_observer_) - table_view_observer_->OnKeyDown(event.key_code()); + if (observer_) + observer_->OnKeyDown(event.key_code()); return false; } @@ -408,8 +404,8 @@ if (event.GetClickCount() == 2) { SelectByViewIndex(row); - if (table_view_observer_) - table_view_observer_->OnDoubleClick(); + if (observer_) + observer_->OnDoubleClick(); } else if (event.GetClickCount() == 1) { ui::ListSelectionModel new_model; ConfigureSelectionModelForEvent(event, &new_model); @@ -509,8 +505,8 @@ selection_model_.set_active(FirstSelectedRow()); if (!selection_model_.empty() && selection_model_.anchor() == -1) selection_model_.set_anchor(FirstSelectedRow()); - if (table_view_observer_) - table_view_observer_->OnSelectionChanged(); + if (observer_) + observer_->OnSelectionChanged(); } gfx::Point TableView::GetKeyboardContextMenuLocation() { @@ -846,8 +842,8 @@ ScrollRectToVisible(vis_rect); } - if (table_view_observer_) - table_view_observer_->OnSelectionChanged(); + if (observer_) + observer_->OnSelectionChanged(); NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true); }
diff --git a/ui/views/controls/table/table_view.h b/ui/views/controls/table/table_view.h index 079edaad..6d1c184 100644 --- a/ui/views/controls/table/table_view.h +++ b/ui/views/controls/table/table_view.h
@@ -116,10 +116,6 @@ // Returns the number of rows in the TableView. int RowCount() const; - // Returns the number of selected rows. - // TODO(sky): remove this and force callers to use selection_model(). - int SelectedRowCount(); - // Selects the specified item, making sure it's visible. void Select(int model_row); @@ -141,11 +137,8 @@ // or not). bool HasColumn(int id) const; - // TODO(sky): rename to set_observer(). - void SetObserver(TableViewObserver* observer) { - table_view_observer_ = observer; - } - TableViewObserver* observer() const { return table_view_observer_; } + void set_observer(TableViewObserver* observer) { observer_ = observer; } + TableViewObserver* observer() const { return observer_; } const std::vector<VisibleColumn>& visible_columns() const { return visible_columns_; @@ -331,8 +324,7 @@ // is selected then. bool select_on_remove_ = true; - // TODO(sky): rename to observer_. - TableViewObserver* table_view_observer_; + TableViewObserver* observer_; // The selection, in terms of the model. ui::ListSelectionModel selection_model_;
diff --git a/ui/views/controls/table/table_view_unittest.cc b/ui/views/controls/table/table_view_unittest.cc index c94994c..d72345c 100644 --- a/ui/views/controls/table/table_view_unittest.cc +++ b/ui/views/controls/table/table_view_unittest.cc
@@ -645,7 +645,7 @@ // Assertions around changing the selection. TEST_F(TableViewTest, Selection) { TableViewObserverImpl observer; - table_->SetObserver(&observer); + table_->set_observer(&observer); // Initially no selection. EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString()); @@ -674,7 +674,7 @@ EXPECT_EQ(0, observer.GetChangedCountAndClear()); EXPECT_EQ("active=3 anchor=3 selection=3", SelectionStateAsString()); - table_->SetObserver(NULL); + table_->set_observer(NULL); } // 0 1 2 3: @@ -686,7 +686,7 @@ // remove 0 -> 0 (none selected) TEST_F(TableViewTest, SelectionNoSelectOnRemove) { TableViewObserverImpl observer; - table_->SetObserver(&observer); + table_->set_observer(&observer); table_->set_select_on_remove(false); // Initially no selection. @@ -724,7 +724,7 @@ EXPECT_EQ(1, observer.GetChangedCountAndClear()); EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString()); - table_->SetObserver(nullptr); + table_->set_observer(nullptr); } // Verifies selection works by way of a gesture. @@ -733,14 +733,14 @@ EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString()); TableViewObserverImpl observer; - table_->SetObserver(&observer); + table_->set_observer(&observer); // Click on the first row, should select it. TapOnRow(0); EXPECT_EQ(1, observer.GetChangedCountAndClear()); EXPECT_EQ("active=0 anchor=0 selection=0", SelectionStateAsString()); - table_->SetObserver(NULL); + table_->set_observer(NULL); } // Verifies up/down correctly navigates through groups. @@ -761,7 +761,7 @@ table_->SetGrouper(&grouper); TableViewObserverImpl observer; - table_->SetObserver(&observer); + table_->set_observer(&observer); // Initially no selection. EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString()); @@ -870,7 +870,7 @@ EXPECT_EQ(0, observer.GetChangedCountAndClear()); EXPECT_EQ("active=2 anchor=2 selection=2", SelectionStateAsString()); - table_->SetObserver(NULL); + table_->set_observer(NULL); } // Verifies home/end do the right thing. @@ -891,7 +891,7 @@ table_->SetGrouper(&grouper); TableViewObserverImpl observer; - table_->SetObserver(&observer); + table_->set_observer(&observer); // Initially no selection. EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString()); @@ -904,7 +904,7 @@ EXPECT_EQ(1, observer.GetChangedCountAndClear()); EXPECT_EQ("active=4 anchor=4 selection=3 4", SelectionStateAsString()); - table_->SetObserver(NULL); + table_->set_observer(NULL); } // Verifies multiple selection gestures work (control-click, shift-click ...). @@ -928,7 +928,7 @@ EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString()); TableViewObserverImpl observer; - table_->SetObserver(&observer); + table_->set_observer(&observer); // Click on the first row, should select it and the second row. ClickOnRow(0, 0); @@ -960,7 +960,7 @@ EXPECT_EQ(1, observer.GetChangedCountAndClear()); EXPECT_EQ("active=4 anchor=4 selection=3 4", SelectionStateAsString()); - table_->SetObserver(NULL); + table_->set_observer(NULL); } // Verifies multiple selection gestures work when sorted. @@ -993,7 +993,7 @@ EXPECT_EQ("active=-1 anchor=-1 selection=", SelectionStateAsString()); TableViewObserverImpl observer; - table_->SetObserver(&observer); + table_->set_observer(&observer); // Click on the third row, should select it and the second row. ClickOnRow(2, 0); @@ -1005,7 +1005,7 @@ EXPECT_EQ(1, observer.GetChangedCountAndClear()); EXPECT_EQ("active=2 anchor=4 selection=2 3 4", SelectionStateAsString()); - table_->SetObserver(NULL); + table_->set_observer(NULL); } // Verifies we don't crash after removing the selected row when there is
diff --git a/ui/views/examples/table_example.cc b/ui/views/examples/table_example.cc index abdfebb..041270a 100644 --- a/ui/views/examples/table_example.cc +++ b/ui/views/examples/table_example.cc
@@ -70,7 +70,7 @@ columns.back().alignment = ui::TableColumn::RIGHT; table_ = new TableView(this, columns, ICON_AND_TEXT, true); table_->SetGrouper(this); - table_->SetObserver(this); + table_->set_observer(this); icon1_.allocN32Pixels(16, 16); SkCanvas canvas1(icon1_); canvas1.drawColor(SK_ColorRED);
diff --git a/ui/views/view.cc b/ui/views/view.cc index f28af0c..68c0e0e 100644 --- a/ui/views/view.cc +++ b/ui/views/view.cc
@@ -496,6 +496,10 @@ SchedulePaint(); } +View::Views View::GetChildrenInZOrder() { + return children_; +} + // Transformations ------------------------------------------------------------- gfx::Transform View::GetTransform() const { @@ -954,7 +958,9 @@ // Walk the child Views recursively looking for the View that most // tightly encloses the specified point. - for (auto* child : base::Reversed(children_)) { + View::Views children = GetChildrenInZOrder(); + DCHECK_EQ(child_count(), static_cast<int>(children.size())); + for (auto* child : base::Reversed(children)) { if (!child->visible()) continue; @@ -1473,8 +1479,9 @@ void View::PaintChildren(const ui::PaintContext& context) { TRACE_EVENT1("views", "View::PaintChildren", "class", GetClassName()); - internal::ScopedChildrenLock lock(this); - for (auto* child : children_) { + View::Views children = GetChildrenInZOrder(); + DCHECK_EQ(child_count(), static_cast<int>(children.size())); + for (auto* child : children) { if (!child->layer()) child->Paint(context); } @@ -1628,10 +1635,10 @@ // Iterate backwards through the children so that a child with a layer // which is further to the back is stacked above one which is further to // the front. - internal::ScopedChildrenLock lock(this); - for (auto* child : base::Reversed(children_)) { + View::Views children = GetChildrenInZOrder(); + DCHECK_EQ(child_count(), static_cast<int>(children.size())); + for (auto* child : base::Reversed(children)) child->ReorderChildLayers(parent_layer); - } } }
diff --git a/ui/views/view.h b/ui/views/view.h index ab25806..71b1cd9 100644 --- a/ui/views/view.h +++ b/ui/views/view.h
@@ -192,6 +192,8 @@ void RemoveAllChildViews(bool delete_children); int child_count() const { return static_cast<int>(children_.size()); } + // See also |GetChildrenInZOrder()| below that returns |children_| + // in reverse z-order. bool has_children() const { return !children_.empty(); } // Returns the child view at |index|. @@ -308,6 +310,14 @@ // Returns whether the view is enabled. bool enabled() const { return enabled_; } + // Returns the child views ordered in reverse z-order. That is, views later in + // the returned vector have a higher z-order (are painted later) than those + // early in the vector. The returned vector has exactly the same number of + // Views as |children_|. The default implementation returns |children_|, + // subclass if the paint order should differ from that of |children_|. + // This order is taken into account by painting and targeting implementations. + virtual View::Views GetChildrenInZOrder(); + // Transformations ----------------------------------------------------------- // Methods for setting transformations for a view (e.g. rotation, scaling).
diff --git a/ui/views/view_targeter_delegate.cc b/ui/views/view_targeter_delegate.cc index b20842f..7347141 100644 --- a/ui/views/view_targeter_delegate.cc +++ b/ui/views/view_targeter_delegate.cc
@@ -6,6 +6,7 @@ #include <limits.h> +#include "base/containers/adapters.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/views/rect_based_targeting_utils.h" #include "ui/views/view.h" @@ -42,9 +43,9 @@ // from this function call if point-based targeting were used. View* point_view = NULL; - for (int i = root->child_count() - 1; i >= 0; --i) { - View* child = root->child_at(i); - + View::Views children = root->GetChildrenInZOrder(); + DCHECK_EQ(root->child_count(), static_cast<int>(children.size())); + for (auto* child : base::Reversed(children)) { if (!child->CanProcessEventsWithinSubtree()) continue;
diff --git a/ui/views/view_unittest.cc b/ui/views/view_unittest.cc index 5f42fa7..bb713373 100644 --- a/ui/views/view_unittest.cc +++ b/ui/views/view_unittest.cc
@@ -4669,6 +4669,67 @@ EXPECT_FALSE(view.GetWidget()); } +// A View that keeps the children with a special ID above other children. +class OrderableView : public View { + public: + // ID used by the children that are stacked above other children. + static constexpr int VIEW_ID_RAISED = 1000; + + OrderableView() : View() {} + ~OrderableView() override {} + + View::Views GetChildrenInZOrder() override { + View::Views children; + // Iterate over regular children and later over the raised children to + // create a custom Z-order. + for (int i = 0; i < child_count(); ++i) { + if (child_at(i)->id() != VIEW_ID_RAISED) + children.push_back(child_at(i)); + } + for (int i = 0; i < child_count(); ++i) { + if (child_at(i)->id() == VIEW_ID_RAISED) + children.push_back(child_at(i)); + } + DCHECK_EQ(child_count(), static_cast<int>(children.size())); + return children; + } + + private: + DISALLOW_COPY_AND_ASSIGN(OrderableView); +}; + +TEST_F(ViewTest, ChildViewZOrderChanged) { + const int kChildrenCount = 4; + std::unique_ptr<View> view(new OrderableView()); + view->SetPaintToLayer(true); + for (int i = 0; i < kChildrenCount; ++i) + AddViewWithChildLayer(view.get()); + View::Views children = view->GetChildrenInZOrder(); + const std::vector<ui::Layer*>& layers = view->layer()->children(); + EXPECT_EQ(kChildrenCount, static_cast<int>(layers.size())); + EXPECT_EQ(kChildrenCount, static_cast<int>(children.size())); + for (int i = 0; i < kChildrenCount; ++i) { + EXPECT_EQ(view->child_at(i)->layer(), layers[i]); + EXPECT_EQ(view->child_at(i), children[i]); + } + + // Raise one of the children in z-order and add another child to reorder. + view->child_at(2)->set_id(OrderableView::VIEW_ID_RAISED); + AddViewWithChildLayer(view.get()); + + // 2nd child should be now on top, i.e. the last element in the array returned + // by GetChildrenInZOrder(). Its layer should also be above the others. + // The rest of the children and layers order should be unchanged. + const int expected_order[] = {0, 1, 3, 4, 2}; + children = view->GetChildrenInZOrder(); + EXPECT_EQ(kChildrenCount + 1, static_cast<int>(children.size())); + EXPECT_EQ(kChildrenCount + 1, static_cast<int>(layers.size())); + for (size_t i = 0; i < kChildrenCount + 1; ++i) { + EXPECT_EQ(view->child_at(expected_order[i]), children[i]); + EXPECT_EQ(view->child_at(expected_order[i])->layer(), layers[i]); + } +} + //////////////////////////////////////////////////////////////////////////////// // Observer tests. ////////////////////////////////////////////////////////////////////////////////