diff --git a/DEPS b/DEPS index 74d7453..d94be74 100644 --- a/DEPS +++ b/DEPS
@@ -133,11 +133,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'aeb71ce166c755a09ba4a66f5e6a5d7a22149b12', + 'skia_revision': 'b8e77698ad39494d1de58d97ea7b2fb8579d2490', # 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': '7afc9ca45927216f43bc869135b33134af3a64de', + 'v8_revision': '60263cb67e90fea34c6754f4cb9242351a2cb676', # 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. @@ -145,7 +145,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': '08146a27b7bc07d6a2426591de7f1ec1a06bed42', + 'angle_revision': 'e8247a574956349b7f0a9beaa63c8a7db90e2403', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -153,7 +153,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': 'b6220d071585a765b9ae8a626a5975e4d6fb4ab7', + 'pdfium_revision': '0958e507daa3774ac8996b6e7ee260b9154f8ee5', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -184,7 +184,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. - 'freetype_revision': '2f4b740ce435bc1ad5ef8570bb91ab7cd5682720', + 'freetype_revision': 'fbbcf50367403a6316a013b51690071198962920', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling HarfBuzz # and whatever else without interference from each other. @@ -268,7 +268,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '2bc3169f0d64a07469b73c318a2e4c887f8eb17a', + 'dawn_revision': '2a7b631482d8cb167d5651be130b08549b4dedc8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -802,7 +802,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'f0a719c3731cdc76fb6efd270801145b7afe1243', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '1ffff0a0da2bcb60cd2a94c15081ff491c4f72c0', 'condition': 'checkout_linux', }, @@ -827,7 +827,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'ad39f9d8f8d117ef63fc7d50b207a14017f05c08', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '5716400ae256163c8c91b489ce694e7c561e0c92', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -1177,7 +1177,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '513ef55bd2588a21ecdbd0d743c5aede17d02a9b', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'c9cac42e24593ab65c8c828f7e1b428a7de35df7', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1345,7 +1345,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '6f0b34abee8dba611c253738d955c59f703c147a', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '1ff16c87aa63d4f9b63a238fc0664b5e625e9884', + Var('webrtc_git') + '/src.git' + '@' + '762076b88663ac0225175593cb216040471701e5', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1386,7 +1386,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b28d01ad3a2a4984e35b311e010151d1a51bf881', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@e2260af0009653969ed497da3ae8fd0536338756', 'condition': 'checkout_src_internal', },
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 35de071..7a685ad 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -563,33 +563,6 @@ (), ), ( - r'/\bbase::Bind\(', - ( - 'Please consider using base::Bind{Once,Repeating} instead', - 'of base::Bind. (crbug.com/714018)', - ), - False, - (), - ), - ( - r'/\bbase::Callback<', - ( - 'Please consider using base::{Once,Repeating}Callback instead', - 'of base::Callback. (crbug.com/714018)', - ), - False, - (), - ), - ( - r'/\bbase::Closure\b', - ( - 'Please consider using base::{Once,Repeating}Closure instead', - 'of base::Closure. (crbug.com/714018)', - ), - False, - (), - ), - ( r'/base::SharedMemory(|Handle)', ( 'base::SharedMemory is deprecated. Please use',
diff --git a/WATCHLISTS b/WATCHLISTS index 869f743..ca45689 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -118,9 +118,6 @@ 'arc_common': { 'filepath': 'components/arc/common/', }, - 'arc_fileapi': { - 'filepath': 'chrome/browser/chromeos/arc/fileapi' - }, 'arc_ime': { 'filepath': 'chrome/browser/chromeos/arc/input_method_manager/'\ '|components/arc/ime/' @@ -1922,7 +1919,6 @@ 'arc-reviews+chromium@google.com'], 'arc_auth': ['khmel+watch@chromium.org'], 'arc_common': ['hashimoto+watch@chromium.org'], - 'arc_fileapi': ['nya+watch@chromium.org'], 'arc_ime': ['yhanada+watch@chromium.org'], 'arc_kiosk': ['poromov+watch@chromium.org'], 'arc_net': ['abhishekbh@chromium.org',
diff --git a/ash/accelerators/accelerator_controller_impl.cc b/ash/accelerators/accelerator_controller_impl.cc index cffe64e..90a6450d 100644 --- a/ash/accelerators/accelerator_controller_impl.cc +++ b/ash/accelerators/accelerator_controller_impl.cc
@@ -208,7 +208,7 @@ void RecordImeSwitchByAccelerator() { UMA_HISTOGRAM_ENUMERATION("InputMethod.ImeSwitch", - ImeSwitchType::kAccelerator, ImeSwitchType::kCount); + ImeSwitchType::kAccelerator); } void HandleCycleBackwardMRU(const ui::Accelerator& accelerator) {
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc index 6f29011..483a7b6 100644 --- a/ash/app_list/app_list_controller_impl.cc +++ b/ash/app_list/app_list_controller_impl.cc
@@ -182,7 +182,8 @@ return &search_model_; } -void AppListControllerImpl::AddItem(AppListItemMetadataPtr item_data) { +void AppListControllerImpl::AddItem( + std::unique_ptr<ash::AppListItemMetadata> item_data) { const std::string folder_id = item_data->folder_id; if (folder_id.empty()) model_->AddItem(CreateAppListItem(std::move(item_data))); @@ -190,8 +191,9 @@ AddItemToFolder(std::move(item_data), folder_id); } -void AppListControllerImpl::AddItemToFolder(AppListItemMetadataPtr item_data, - const std::string& folder_id) { +void AppListControllerImpl::AddItemToFolder( + std::unique_ptr<ash::AppListItemMetadata> item_data, + const std::string& folder_id) { // When we're setting a whole model of a profile, each item may have its // folder id set properly. However, |AppListModel::AddItemToFolder| requires // the item to add is not in the target folder yet, and sets its folder id @@ -259,8 +261,9 @@ search_model_.PublishResults(std::move(new_results)); } -void AppListControllerImpl::SetItemMetadata(const std::string& id, - AppListItemMetadataPtr data) { +void AppListControllerImpl::SetItemMetadata( + const std::string& id, + std::unique_ptr<ash::AppListItemMetadata> data) { app_list::AppListItem* item = model_->FindItem(id); if (!item) return; @@ -314,7 +317,7 @@ void AppListControllerImpl::SetModelData( int profile_id, - std::vector<AppListItemMetadataPtr> apps, + std::vector<std::unique_ptr<ash::AppListItemMetadata>> apps, bool is_search_engine_google) { // Clear old model data. model_->DeleteAllItems(); @@ -394,7 +397,7 @@ model_->SetItemPosition(oem_folder, oem_position); } model_->SetItemName(oem_folder, oem_folder_name); - std::move(callback).Run(oem_folder->CloneMetadata()); + std::move(callback).Run(); } void AppListControllerImpl::ResolveOemFolderPosition( @@ -402,7 +405,7 @@ ResolveOemFolderPositionCallback callback) { // In ash: app_list::AppListFolderItem* ash_oem_folder = FindFolderItem(kOemFolderId); - ash::mojom::AppListItemMetadataPtr metadata = nullptr; + std::unique_ptr<ash::AppListItemMetadata> metadata; if (ash_oem_folder) { const syncer::StringOrdinal& oem_folder_pos = preferred_oem_position.IsValid() ? preferred_oem_position @@ -1270,7 +1273,7 @@ } std::unique_ptr<app_list::AppListItem> AppListControllerImpl::CreateAppListItem( - AppListItemMetadataPtr metadata) { + std::unique_ptr<ash::AppListItemMetadata> metadata) { std::unique_ptr<app_list::AppListItem> app_list_item = metadata->is_folder ? std::make_unique<app_list::AppListFolderItem>(metadata->id)
diff --git a/ash/app_list/app_list_controller_impl.h b/ash/app_list/app_list_controller_impl.h index 49ba387..c289b26 100644 --- a/ash/app_list/app_list_controller_impl.h +++ b/ash/app_list/app_list_controller_impl.h
@@ -77,8 +77,8 @@ // app_list::AppListController: void SetClient(app_list::AppListClient* client) override; - void AddItem(AppListItemMetadataPtr app_item) override; - void AddItemToFolder(AppListItemMetadataPtr app_item, + void AddItem(std::unique_ptr<ash::AppListItemMetadata> app_item) override; + void AddItemToFolder(std::unique_ptr<ash::AppListItemMetadata> app_item, const std::string& folder_id) override; void RemoveItem(const std::string& id) override; void RemoveUninstalledItem(const std::string& id) override; @@ -97,13 +97,13 @@ void PublishSearchResults( std::vector<SearchResultMetadataPtr> results) override; void SetItemMetadata(const std::string& id, - AppListItemMetadataPtr data) override; + std::unique_ptr<ash::AppListItemMetadata> data) override; void SetItemIcon(const std::string& id, const gfx::ImageSkia& icon) override; void SetItemIsInstalling(const std::string& id, bool is_installing) override; void SetItemPercentDownloaded(const std::string& id, int32_t percent_downloaded) override; void SetModelData(int profile_id, - std::vector<AppListItemMetadataPtr> apps, + std::vector<std::unique_ptr<ash::AppListItemMetadata>> apps, bool is_search_engine_google) override; void SetSearchResultMetadata(SearchResultMetadataPtr metadata) override; @@ -313,7 +313,7 @@ syncer::StringOrdinal GetOemFolderPos(); std::unique_ptr<app_list::AppListItem> CreateAppListItem( - AppListItemMetadataPtr metadata); + std::unique_ptr<ash::AppListItemMetadata> metadata); app_list::AppListFolderItem* FindFolderItem(const std::string& folder_id); // Update the visibility of Assistant functionality.
diff --git a/ash/app_list/model/app_list_item.cc b/ash/app_list/model/app_list_item.cc index 11d1bb27..bd9ecd7 100644 --- a/ash/app_list/model/app_list_item.cc +++ b/ash/app_list/model/app_list_item.cc
@@ -10,18 +10,11 @@ namespace app_list { AppListItem::AppListItem(const std::string& id) - : metadata_(ash::mojom::AppListItemMetadata::New( - id, - std::string() /* name */, - std::string() /* short_name */, - std::string() /* folder_id */, - syncer::StringOrdinal() /* position */, - false /* is_folder */, - false /* is_persistent */, - gfx::ImageSkia() /* icon */, - false /* is_page_break */)), + : metadata_(std::make_unique<ash::AppListItemMetadata>()), is_installing_(false), - percent_downloaded_(-1) {} + percent_downloaded_(-1) { + metadata_->id = id; +} AppListItem::~AppListItem() { for (auto& observer : observers_)
diff --git a/ash/app_list/model/app_list_item.h b/ash/app_list/model/app_list_item.h index 04512b4d..c1a55a8 100644 --- a/ash/app_list/model/app_list_item.h +++ b/ash/app_list/model/app_list_item.h
@@ -7,10 +7,12 @@ #include <stddef.h> +#include <memory> #include <string> #include <utility> #include "ash/app_list/model/app_list_model_export.h" +#include "ash/public/cpp/app_list/app_list_types.h" #include "ash/public/interfaces/app_list.mojom.h" #include "base/macros.h" #include "base/observer_list.h" @@ -34,6 +36,8 @@ // and action to be executed when the AppListItemView is activated. class APP_LIST_MODEL_EXPORT AppListItem { public: + using AppListItemMetadata = ash::AppListItemMetadata; + explicit AppListItem(const std::string& id); virtual ~AppListItem(); @@ -60,14 +64,12 @@ const std::string& folder_id() const { return metadata_->folder_id; } const syncer::StringOrdinal& position() const { return metadata_->position; } - void SetMetadata(ash::mojom::AppListItemMetadataPtr metadata) { + void SetMetadata(std::unique_ptr<AppListItemMetadata> metadata) { metadata_ = std::move(metadata); } - const ash::mojom::AppListItemMetadata* GetMetadata() const { - return metadata_.get(); - } - ash::mojom::AppListItemMetadataPtr CloneMetadata() const { - return metadata_.Clone(); + const AppListItemMetadata* GetMetadata() const { return metadata_.get(); } + std::unique_ptr<AppListItemMetadata> CloneMetadata() const { + return std::make_unique<AppListItemMetadata>(*metadata_); } void AddObserver(AppListItemObserver* observer); @@ -97,7 +99,7 @@ protected: // Subclasses also have mutable access to the metadata ptr. - ash::mojom::AppListItemMetadata* metadata() { return metadata_.get(); } + AppListItemMetadata* metadata() { return metadata_.get(); } friend class ::FastShowPickler; friend class ash::AppListControllerImpl; @@ -130,7 +132,7 @@ private: friend class AppListModelTest; - ash::mojom::AppListItemMetadataPtr metadata_; + std::unique_ptr<AppListItemMetadata> metadata_; // A shortened name for the item, used for display. std::string short_name_;
diff --git a/ash/app_list/test/test_app_list_client.h b/ash/app_list/test/test_app_list_client.h index dff11810..edd843e 100644 --- a/ash/app_list/test/test_app_list_client.h +++ b/ash/app_list/test/test_app_list_client.h
@@ -44,11 +44,11 @@ void OnAppListTargetVisibilityChanged(bool visible) override {} void OnAppListVisibilityChanged(bool visible) override {} void OnFolderCreated(int profile_id, - mojom::AppListItemMetadataPtr item) override {} + std::unique_ptr<AppListItemMetadata> item) override {} void OnFolderDeleted(int profile_id, - mojom::AppListItemMetadataPtr item) override {} + std::unique_ptr<AppListItemMetadata> item) override {} void OnItemUpdated(int profile_id, - mojom::AppListItemMetadataPtr item) override {} + std::unique_ptr<AppListItemMetadata> item) override {} void OnPageBreakItemAdded(int profile_id, const std::string& id, const syncer::StringOrdinal& position) override {}
diff --git a/ash/app_list/views/top_icon_animation_view.h b/ash/app_list/views/top_icon_animation_view.h index ff71d936..aaed713 100644 --- a/ash/app_list/views/top_icon_animation_view.h +++ b/ash/app_list/views/top_icon_animation_view.h
@@ -59,7 +59,7 @@ // location to the small icon inside the folder icon. void TransformView(); - // views::View + // views::View: const char* GetClassName() const override; private:
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index d17d579..abbf7f8 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -887,7 +887,7 @@ Show network list. <ph name="STATE_TEXT">$1<ex>Connected to public wifi</ex></ph> </message> - <!-- Status Tray Network strings --> + <!-- Status Tray Bluetooth strings --> <message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_DISPLAY_PINCODE" desc="Bluetooth pairing message typically shown on a request from a 2.0 device that has a keyboard."> Bluetooth device "<ph name="DEVICE_NAME">$1<ex>Nexus S</ex></ph>" would like permission to pair. Please enter this PIN code on that device: <ph name="PINCODE">$2<ex>123456</ex></ph> </message> @@ -1230,18 +1230,12 @@ <message name="IDS_ASH_STATUS_TRAY_NETWORK_CONNECTING" desc="Message for the network tray tooltip and network list when connecting to a network."> Connecting to <ph name="NAME">$1<ex>GoogleGuest</ex></ph> </message> - <message name="IDS_ASH_STATUS_TRAY_NETWORK_RECONNECTING" desc="Message for the network tray tooltip and network list when reconnecting to a network."> - Reconnecting to <ph name="NAME">$1<ex>Company VPN</ex></ph> - </message> <message name="IDS_ASH_STATUS_TRAY_NETWORK_LIST_ACTIVATE" desc="Message for the network list to activate the network."> Activate <ph name="NETWORKSERVICE">$1<ex>YBH Cellular</ex></ph> </message> <message name="IDS_ASH_STATUS_TRAY_NETWORK_LIST_ACTIVATING" desc="Message for the network list when activating a network."> <ph name="NAME">$1<ex>YBH Cellular</ex></ph>: Activating... </message> - <message name="IDS_ASH_STATUS_TRAY_NETWORK_LIST_CONNECTING" desc="Message for the network list when connecting to a network."> - <ph name="NAME">$1<ex>GoogleGuest</ex></ph>: Connecting... - </message> <message name="IDS_ASH_STATUS_TRAY_NETWORK_NOT_CONNECTED" desc="Description in status area or network list when no network is connected."> No network </message>
diff --git a/ash/ime/ime_controller.cc b/ash/ime/ime_controller.cc index 0e57214..3c906d7 100644 --- a/ash/ime/ime_controller.cc +++ b/ash/ime/ime_controller.cc
@@ -244,8 +244,7 @@ UMA_HISTOGRAM_ENUMERATION("InputMethod.ModeChangeKeyAction", ModeChangeKeyAction::kSwitchIme); UMA_HISTOGRAM_ENUMERATION("InputMethod.ImeSwitch", - ImeSwitchType::kModeChangeKey, - ImeSwitchType::kCount); + ImeSwitchType::kModeChangeKey); } else { client_->ShowModeIndicator();
diff --git a/ash/ime/ime_switch_type.h b/ash/ime/ime_switch_type.h index f43af4d..6058092a 100644 --- a/ash/ime/ime_switch_type.h +++ b/ash/ime/ime_switch_type.h
@@ -14,7 +14,7 @@ kTray = 0, kAccelerator = 1, kModeChangeKey = 2, - kCount = 3, + kMaxValue = kModeChangeKey, }; } // namespace ash
diff --git a/ash/keyboard/ui/keyboard_controller.cc b/ash/keyboard/ui/keyboard_controller.cc index c747292..baefcce 100644 --- a/ash/keyboard/ui/keyboard_controller.cc +++ b/ash/keyboard/ui/keyboard_controller.cc
@@ -219,7 +219,7 @@ show_on_keyboard_window_load_ = false; keyboard_locked_ = false; - DCHECK_EQ(model_.state(), KeyboardControllerState::kInitial); + DCHECK_EQ(model_.state(), KeyboardUIState::kInitial); ui_->SetController(this); SetContainerBehaviorInternal(mojom::ContainerType::kFullWidth); visual_bounds_in_root_ = gfx::Rect(); @@ -251,8 +251,8 @@ // Return to the INITIAL state to ensure that transitions entering a state // is equal to transitions leaving the state. - if (model_.state() != KeyboardControllerState::kInitial) - ChangeState(KeyboardControllerState::kInitial); + if (model_.state() != KeyboardUIState::kInitial) + ChangeState(KeyboardUIState::kInitial); // TODO(https://crbug.com/731537): Move KeyboardController members into a // subobject so we can just put this code into the subobject destructor. @@ -360,8 +360,8 @@ void KeyboardController::NotifyKeyboardWindowLoaded() { const bool should_show = show_on_keyboard_window_load_; - if (model_.state() == KeyboardControllerState::kLoadingExtension) - ChangeState(KeyboardControllerState::kHidden); + if (model_.state() == KeyboardUIState::kLoading) + ChangeState(KeyboardUIState::kHidden); if (should_show) { // The window height is set to 0 initially or before switch to an IME in a // different extension. Virtual keyboard window may wait for this bounds @@ -530,16 +530,16 @@ TRACE_EVENT0("vk", "HideKeyboard"); switch (model_.state()) { - case KeyboardControllerState::kUnknown: - case KeyboardControllerState::kInitial: - case KeyboardControllerState::kHidden: + case KeyboardUIState::kUnknown: + case KeyboardUIState::kInitial: + case KeyboardUIState::kHidden: return; - case KeyboardControllerState::kLoadingExtension: + case KeyboardUIState::kLoading: show_on_keyboard_window_load_ = false; return; - case KeyboardControllerState::kWillHide: - case KeyboardControllerState::kShown: { + case KeyboardUIState::kWillHide: + case KeyboardUIState::kShown: { SetTouchEventLogging(true /* enable */); // Log whether this was a user or system (automatic) action. @@ -591,7 +591,7 @@ } ui_->HideKeyboardWindow(); - ChangeState(KeyboardControllerState::kHidden); + ChangeState(KeyboardUIState::kHidden); for (KeyboardControllerObserver& observer : observer_list_) observer.OnKeyboardHidden(reason == HIDE_REASON_SYSTEM_TEMPORARY); @@ -619,10 +619,10 @@ } void KeyboardController::HideKeyboardImplicitlyBySystem() { - if (model_.state() != KeyboardControllerState::kShown || keyboard_locked_) + if (model_.state() != KeyboardUIState::kShown || keyboard_locked_) return; - ChangeState(KeyboardControllerState::kWillHide); + ChangeState(KeyboardUIState::kWillHide); base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, @@ -634,7 +634,7 @@ // private void KeyboardController::HideAnimationFinished() { - if (model_.state() == KeyboardControllerState::kHidden) { + if (model_.state() == KeyboardUIState::kHidden) { if (queued_container_type_) { SetContainerBehaviorInternal(queued_container_type_->container_type()); // The position of the container window will be adjusted shortly in @@ -701,7 +701,7 @@ } void KeyboardController::LoadKeyboardWindowInBackground() { - DCHECK_EQ(model_.state(), KeyboardControllerState::kInitial); + DCHECK_EQ(model_.state(), KeyboardUIState::kInitial); TRACE_EVENT0("vk", "LoadKeyboardWindowInBackground"); @@ -716,7 +716,7 @@ keyboard_window->AddObserver(this); parent_container_->AddChild(keyboard_window); - ChangeState(KeyboardControllerState::kLoadingExtension); + ChangeState(KeyboardUIState::kLoading); } ui::InputMethod* KeyboardController::GetInputMethodForTest() { @@ -796,10 +796,10 @@ if (should_hide) { switch (model_.state()) { - case KeyboardControllerState::kLoadingExtension: + case KeyboardUIState::kLoading: show_on_keyboard_window_load_ = false; return; - case KeyboardControllerState::kShown: + case KeyboardUIState::kShown: HideKeyboardImplicitlyBySystem(); return; default: @@ -807,11 +807,11 @@ } } else { switch (model_.state()) { - case KeyboardControllerState::kWillHide: + case KeyboardUIState::kWillHide: // Abort a pending keyboard hide. - ChangeState(KeyboardControllerState::kShown); + ChangeState(KeyboardUIState::kShown); return; - case KeyboardControllerState::kHidden: + case KeyboardUIState::kHidden: if (focused && is_web) ShowKeyboardIfWithinTransientBlurThreshold(); return; @@ -846,7 +846,7 @@ void KeyboardController::PopulateKeyboardContent( aura::Window* target_container) { - DCHECK_NE(model_.state(), KeyboardControllerState::kInitial); + DCHECK_NE(model_.state(), KeyboardUIState::kInitial); DVLOG(1) << "PopulateKeyboardContent: " << StateToStr(model_.state()); TRACE_EVENT0("vk", "PopulateKeyboardContent"); @@ -858,9 +858,9 @@ DCHECK_EQ(parent_container_, keyboard_window->parent()); switch (model_.state()) { - case KeyboardControllerState::kShown: + case KeyboardUIState::kShown: return; - case KeyboardControllerState::kLoadingExtension: + case KeyboardUIState::kLoading: show_on_keyboard_window_load_ = true; return; default: @@ -872,14 +872,14 @@ SetTouchEventLogging(false /* enable */); switch (model_.state()) { - case KeyboardControllerState::kWillHide: - ChangeState(KeyboardControllerState::kShown); + case KeyboardUIState::kWillHide: + ChangeState(KeyboardUIState::kShown); return; default: break; } - DCHECK_EQ(model_.state(), KeyboardControllerState::kHidden); + DCHECK_EQ(model_.state(), KeyboardUIState::kHidden); // If the container is not animating, makes sure the position and opacity // are at begin states for animation. @@ -907,7 +907,7 @@ // gets destroyed. queued_container_type_ = nullptr; - ChangeState(KeyboardControllerState::kShown); + ChangeState(KeyboardUIState::kShown); UMA_HISTOGRAM_ENUMERATION("InputMethod.VirtualKeyboard.ContainerBehavior", GetActiveContainerType()); @@ -915,7 +915,7 @@ bool KeyboardController::WillHideKeyboard() const { bool res = weak_factory_will_hide_.HasWeakPtrs(); - DCHECK_EQ(res, model_.state() == KeyboardControllerState::kWillHide); + DCHECK_EQ(res, model_.state() == KeyboardUIState::kWillHide); return res; } @@ -924,18 +924,18 @@ observer.OnKeyboardConfigChanged(); } -void KeyboardController::ChangeState(KeyboardControllerState state) { +void KeyboardController::ChangeState(KeyboardUIState state) { model_.ChangeState(state); - if (state != KeyboardControllerState::kWillHide) + if (state != KeyboardUIState::kWillHide) weak_factory_will_hide_.InvalidateWeakPtrs(); - if (state != KeyboardControllerState::kLoadingExtension) + if (state != KeyboardUIState::kLoading) show_on_keyboard_window_load_ = false; weak_factory_report_lingering_state_.InvalidateWeakPtrs(); switch (model_.state()) { - case KeyboardControllerState::kLoadingExtension: - case KeyboardControllerState::kWillHide: + case KeyboardUIState::kLoading: + case KeyboardUIState::kWillHide: base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::BindOnce(&KeyboardController::ReportLingeringState, @@ -1022,7 +1022,7 @@ return; } - if (model_.state() == KeyboardControllerState::kShown) { + if (model_.state() == KeyboardUIState::kShown) { // Keyboard is already shown. Hiding the keyboard at first then switching // container type. queued_container_type_ = std::make_unique<QueuedContainerType>( @@ -1054,7 +1054,7 @@ } bool KeyboardController::IsKeyboardVisible() { - if (model_.state() == KeyboardControllerState::kShown) { + if (model_.state() == KeyboardUIState::kShown) { DCHECK(IsEnabled()); return true; }
diff --git a/ash/keyboard/ui/keyboard_controller.h b/ash/keyboard/ui/keyboard_controller.h index 4d99e54..a18377b 100644 --- a/ash/keyboard/ui/keyboard_controller.h +++ b/ash/keyboard/ui/keyboard_controller.h
@@ -232,7 +232,7 @@ std::unique_ptr<ContainerBehavior> container_behavior) { container_behavior_ = std::move(container_behavior); } - KeyboardControllerState GetStateForTest() const { return model_.state(); } + KeyboardUIState GetStateForTest() const { return model_.state(); } ui::InputMethod* GetInputMethodForTest(); void EnsureCaretInWorkAreaForTest(const gfx::Rect& occluded_bounds_in_root); @@ -354,11 +354,10 @@ void NotifyKeyboardWindowLoaded(); // Validates the state transition. Called from ChangeState. - void CheckStateTransition(KeyboardControllerState prev, - KeyboardControllerState next); + void CheckStateTransition(KeyboardUIState prev, KeyboardUIState next); // Changes the current state and validates the transition. - void ChangeState(KeyboardControllerState state); + void ChangeState(KeyboardUIState state); // Reports error histogram in case lingering in an intermediate state. void ReportLingeringState();
diff --git a/ash/keyboard/ui/keyboard_ui_model.cc b/ash/keyboard/ui/keyboard_ui_model.cc index b65d0029..054a259 100644 --- a/ash/keyboard/ui/keyboard_ui_model.cc +++ b/ash/keyboard/ui/keyboard_ui_model.cc
@@ -14,43 +14,37 @@ // Returns whether a given state transition is valid. // See the design document linked in https://crbug.com/71990. -bool IsAllowedStateTransition(KeyboardControllerState from, - KeyboardControllerState to) { +bool IsAllowedStateTransition(KeyboardUIState from, KeyboardUIState to) { static const base::NoDestructor< - std::set<std::pair<KeyboardControllerState, KeyboardControllerState>>> + std::set<std::pair<KeyboardUIState, KeyboardUIState>>> kAllowedStateTransition({ // The initial ShowKeyboard scenario // INITIAL -> LOADING_EXTENSION -> HIDDEN -> SHOWN. - {KeyboardControllerState::kInitial, - KeyboardControllerState::kLoadingExtension}, - {KeyboardControllerState::kLoadingExtension, - KeyboardControllerState::kHidden}, - {KeyboardControllerState::kHidden, KeyboardControllerState::kShown}, + {KeyboardUIState::kInitial, KeyboardUIState::kLoading}, + {KeyboardUIState::kLoading, KeyboardUIState::kHidden}, + {KeyboardUIState::kHidden, KeyboardUIState::kShown}, // Hide scenario // SHOWN -> WILL_HIDE -> HIDDEN. - {KeyboardControllerState::kShown, KeyboardControllerState::kWillHide}, - {KeyboardControllerState::kWillHide, - KeyboardControllerState::kHidden}, + {KeyboardUIState::kShown, KeyboardUIState::kWillHide}, + {KeyboardUIState::kWillHide, KeyboardUIState::kHidden}, // Focus transition scenario // SHOWN -> WILL_HIDE -> SHOWN. - {KeyboardControllerState::kWillHide, KeyboardControllerState::kShown}, + {KeyboardUIState::kWillHide, KeyboardUIState::kShown}, // HideKeyboard can be called at anytime for example on shutdown. - {KeyboardControllerState::kShown, KeyboardControllerState::kHidden}, + {KeyboardUIState::kShown, KeyboardUIState::kHidden}, // Return to INITIAL when keyboard is disabled. - {KeyboardControllerState::kLoadingExtension, - KeyboardControllerState::kInitial}, - {KeyboardControllerState::kHidden, KeyboardControllerState::kInitial}, + {KeyboardUIState::kLoading, KeyboardUIState::kInitial}, + {KeyboardUIState::kHidden, KeyboardUIState::kInitial}, }); return kAllowedStateTransition->count(std::make_pair(from, to)) == 1; } // Records a state transition for metrics. -void RecordStateTransition(KeyboardControllerState prev, - KeyboardControllerState next) { +void RecordStateTransition(KeyboardUIState prev, KeyboardUIState next) { const bool valid_transition = IsAllowedStateTransition(prev, next); // Emit UMA @@ -68,26 +62,26 @@ } // namespace -std::string StateToStr(KeyboardControllerState state) { +std::string StateToStr(KeyboardUIState state) { switch (state) { - case KeyboardControllerState::kUnknown: + case KeyboardUIState::kUnknown: return "UNKNOWN"; - case KeyboardControllerState::kInitial: + case KeyboardUIState::kInitial: return "INITIAL"; - case KeyboardControllerState::kLoadingExtension: - return "LOADING_EXTENSION"; - case KeyboardControllerState::kShown: + case KeyboardUIState::kLoading: + return "LOADING"; + case KeyboardUIState::kShown: return "SHOWN"; - case KeyboardControllerState::kWillHide: + case KeyboardUIState::kWillHide: return "WILL_HIDE"; - case KeyboardControllerState::kHidden: + case KeyboardUIState::kHidden: return "HIDDEN"; } } KeyboardUIModel::KeyboardUIModel() = default; -void KeyboardUIModel::ChangeState(KeyboardControllerState new_state) { +void KeyboardUIModel::ChangeState(KeyboardUIState new_state) { RecordStateTransition(state_, new_state); if (new_state == state_)
diff --git a/ash/keyboard/ui/keyboard_ui_model.h b/ash/keyboard/ui/keyboard_ui_model.h index 94a593f3..7a5497b 100644 --- a/ash/keyboard/ui/keyboard_ui_model.h +++ b/ash/keyboard/ui/keyboard_ui_model.h
@@ -13,21 +13,20 @@ namespace keyboard { -// TODO(https://crbug.com/964191): Change this to be part of the model. -// Represents the current state of the keyboard managed by the controller. +// Represents the current state of the keyboard UI. // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. -enum class KeyboardControllerState { +enum class KeyboardUIState { kUnknown = 0, // Keyboard has never been shown. kInitial = 1, // Waiting for an extension to be loaded. Will move to HIDDEN if this is // loading pre-emptively, otherwise will move to SHOWN. - kLoadingExtension = 2, + kLoading = 2, // kShowing = 3, // no longer used // Keyboard is shown. kShown = 4, - // Keyboard is still shown, but will move to HIDING in a short period, or if + // Keyboard is still shown, but will move to HIDDEN in a short period, or if // an input element gets focused again, will move to SHOWN. kWillHide = 5, // kHiding = 6, // no longer used @@ -36,8 +35,8 @@ kMaxValue = kHidden }; -// Convert a state into a string. -std::string StateToStr(KeyboardControllerState state); +// Returns the string representation of a keyboard UI state. +std::string StateToStr(KeyboardUIState state); // Model for the virtual keyboard UI. class KEYBOARD_EXPORT KeyboardUIModel { @@ -45,14 +44,14 @@ KeyboardUIModel(); // Get the current state of the keyboard UI. - KeyboardControllerState state() const { return state_; } + KeyboardUIState state() const { return state_; } // Changes the current state to another. Only accepts valid state transitions. - void ChangeState(KeyboardControllerState new_state); + void ChangeState(KeyboardUIState new_state); private: // Current state of the keyboard UI. - KeyboardControllerState state_ = KeyboardControllerState::kInitial; + KeyboardUIState state_ = KeyboardUIState::kInitial; DISALLOW_COPY_AND_ASSIGN(KeyboardUIModel); };
diff --git a/ash/keyboard/ui/test/keyboard_test_util.cc b/ash/keyboard/ui/test/keyboard_test_util.cc index a93958a..8b1e48d 100644 --- a/ash/keyboard/ui/test/keyboard_test_util.cc +++ b/ash/keyboard/ui/test/keyboard_test_util.cc
@@ -55,7 +55,7 @@ // single RunUntilIdle call. base::RunLoop run_loop; while (KeyboardController::Get()->GetStateForTest() == - KeyboardControllerState::kLoadingExtension) { + KeyboardUIState::kLoading) { run_loop.RunUntilIdle(); } return true; @@ -82,18 +82,15 @@ DCHECK(keyboard_controller->IsEnabled()); // KeyboardController sets its state to SHOWN when it is about to show. - return keyboard_controller->GetStateForTest() == - KeyboardControllerState::kShown; + return keyboard_controller->GetStateForTest() == KeyboardUIState::kShown; } bool IsKeyboardHiding() { auto* keyboard_controller = KeyboardController::Get(); DCHECK(keyboard_controller->IsEnabled()); - return keyboard_controller->GetStateForTest() == - KeyboardControllerState::kWillHide || - keyboard_controller->GetStateForTest() == - KeyboardControllerState::kHidden; + return keyboard_controller->GetStateForTest() == KeyboardUIState::kWillHide || + keyboard_controller->GetStateForTest() == KeyboardUIState::kHidden; } gfx::Rect KeyboardBoundsFromRootBounds(const gfx::Rect& root_bounds,
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn index 6d60872..3edda99 100644 --- a/ash/public/cpp/BUILD.gn +++ b/ash/public/cpp/BUILD.gn
@@ -148,7 +148,6 @@ "//chromeos/constants", "//chromeos/dbus/power:power_manager_proto", "//components/prefs", - "//components/sync:rest_of_sync", "//mojo/public/cpp/bindings", "//services/service_manager/public/cpp", "//services/ws/public/mojom", @@ -192,6 +191,7 @@ defines = [ "ASH_PUBLIC_IMPLEMENTATION" ] public_deps = [ + "//components/sync:rest_of_sync", "//ui/gfx", ] }
diff --git a/ash/public/cpp/app_list/app_list_client.h b/ash/public/cpp/app_list/app_list_client.h index 9319db30..739c746 100644 --- a/ash/public/cpp/app_list/app_list_client.h +++ b/ash/public/cpp/app_list/app_list_client.h
@@ -99,14 +99,17 @@ const std::string& id, GetContextMenuModelCallback callback) = 0; // Invoked when a folder is created in Ash (e.g. merge items into a folder). - virtual void OnFolderCreated(int profile_id, - ash::mojom::AppListItemMetadataPtr folder) = 0; + virtual void OnFolderCreated( + int profile_id, + std::unique_ptr<ash::AppListItemMetadata> folder) = 0; // Invoked when a folder has only one item left and so gets removed. - virtual void OnFolderDeleted(int profile_id, - ash::mojom::AppListItemMetadataPtr folder) = 0; + virtual void OnFolderDeleted( + int profile_id, + std::unique_ptr<ash::AppListItemMetadata> folder) = 0; // Invoked when user changes a folder's name or an item's position. - virtual void OnItemUpdated(int profile_id, - ash::mojom::AppListItemMetadataPtr folder) = 0; + virtual void OnItemUpdated( + int profile_id, + std::unique_ptr<ash::AppListItemMetadata> folder) = 0; // Invoked when a "page break" item is added with |id| and |position|. virtual void OnPageBreakItemAdded(int profile_id, const std::string& id,
diff --git a/ash/public/cpp/app_list/app_list_controller.h b/ash/public/cpp/app_list/app_list_controller.h index e9cbe3f..ede93977 100644 --- a/ash/public/cpp/app_list/app_list_controller.h +++ b/ash/public/cpp/app_list/app_list_controller.h
@@ -5,6 +5,8 @@ #ifndef ASH_PUBLIC_CPP_APP_LIST_APP_LIST_CONTROLLER_H_ #define ASH_PUBLIC_CPP_APP_LIST_APP_LIST_CONTROLLER_H_ +#include <memory> + #include "ash/public/cpp/ash_public_export.h" // TODO(crbug.com/958134): Remove. #include "ash/public/interfaces/app_list.mojom.h" @@ -25,7 +27,6 @@ // happen while installing/uninstalling apps and the app list gets toggled. class ASH_PUBLIC_EXPORT AppListController { public: - using AppListItemMetadataPtr = ash::mojom::AppListItemMetadataPtr; using SearchResultMetadataPtr = ash::mojom::SearchResultMetadataPtr; // Gets the instance. @@ -35,11 +36,12 @@ virtual void SetClient(AppListClient* client) = 0; // Adds an item to AppListModel. - virtual void AddItem(AppListItemMetadataPtr app_item) = 0; + virtual void AddItem(std::unique_ptr<ash::AppListItemMetadata> app_item) = 0; // Adds an item into a certain folder in AppListModel. - virtual void AddItemToFolder(AppListItemMetadataPtr app_item, - const std::string& folder_id) = 0; + virtual void AddItemToFolder( + std::unique_ptr<ash::AppListItemMetadata> app_item, + const std::string& folder_id) = 0; // Removes an item by its id from AppListModel. virtual void RemoveItem(const std::string& id) = 0; @@ -85,8 +87,9 @@ std::vector<SearchResultMetadataPtr> results) = 0; // Updates an item's metadata (e.g. name, position, etc). - virtual void SetItemMetadata(const std::string& id, - AppListItemMetadataPtr data) = 0; + virtual void SetItemMetadata( + const std::string& id, + std::unique_ptr<ash::AppListItemMetadata> data) = 0; // Updates an item's icon. virtual void SetItemIcon(const std::string& id, @@ -101,9 +104,10 @@ int32_t percent_downloaded) = 0; // Update the whole model, usually when profile changes happen in Chrome. - virtual void SetModelData(int profile_id, - std::vector<AppListItemMetadataPtr> apps, - bool is_search_engine_google) = 0; + virtual void SetModelData( + int profile_id, + std::vector<std::unique_ptr<ash::AppListItemMetadata>> apps, + bool is_search_engine_google) = 0; // Updates a search rresult's metadata. virtual void SetSearchResultMetadata(SearchResultMetadataPtr metadata) = 0; @@ -131,8 +135,7 @@ // creating; if it's invalid then the final position // is determined in Ash. // |oem_folder|: the meta data of the existing/created OEM folder. - using FindOrCreateOemFolderCallback = - base::OnceCallback<void(AppListItemMetadataPtr)>; + using FindOrCreateOemFolderCallback = base::OnceClosure; virtual void FindOrCreateOemFolder( const std::string& oem_folder_name, const syncer::StringOrdinal& preferred_oem_position, @@ -144,7 +147,7 @@ // Ash. // |oem_folder|: the meta data of the OEM folder, or null if it doesn't exist. using ResolveOemFolderPositionCallback = - base::OnceCallback<void(AppListItemMetadataPtr)>; + base::OnceCallback<void(std::unique_ptr<ash::AppListItemMetadata>)>; virtual void ResolveOemFolderPosition( const syncer::StringOrdinal& preferred_oem_position, ResolveOemFolderPositionCallback callback) = 0;
diff --git a/ash/public/cpp/app_list/app_list_types.cc b/ash/public/cpp/app_list/app_list_types.cc index a16d517..b873b59 100644 --- a/ash/public/cpp/app_list/app_list_types.cc +++ b/ash/public/cpp/app_list/app_list_types.cc
@@ -8,6 +8,14 @@ const char kOemFolderId[] = "ddb1da55-d478-4243-8642-56d3041f0263"; +//////////////////////////////////////////////////////////////////////////////// +// AppListItemMetadata: + +AppListItemMetadata::AppListItemMetadata() = default; +AppListItemMetadata::AppListItemMetadata(const AppListItemMetadata& rhs) = + default; +AppListItemMetadata::~AppListItemMetadata() = default; + OmniBoxZeroStateAction GetOmniBoxZeroStateAction(int button_index) { if (button_index < 0 || button_index >=
diff --git a/ash/public/cpp/app_list/app_list_types.h b/ash/public/cpp/app_list/app_list_types.h index 16ec50f..65e576a 100644 --- a/ash/public/cpp/app_list/app_list_types.h +++ b/ash/public/cpp/app_list/app_list_types.h
@@ -5,9 +5,11 @@ #ifndef ASH_PUBLIC_CPP_APP_LIST_APP_LIST_TYPES_H_ #define ASH_PUBLIC_CPP_APP_LIST_APP_LIST_TYPES_H_ +#include <string> #include <vector> #include "ash/public/cpp/ash_public_export.h" +#include "components/sync/model/string_ordinal.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/range/range.h" @@ -23,6 +25,26 @@ // Id of OEM folder in app list. ASH_PUBLIC_EXPORT extern const char kOemFolderId[]; +// A structure holding the common information which is sent between ash and, +// chrome representing an app list item. +struct ASH_PUBLIC_EXPORT AppListItemMetadata { + AppListItemMetadata(); + AppListItemMetadata(const AppListItemMetadata& rhs); + ~AppListItemMetadata(); + + std::string id; // Id of the app list item. + std::string name; // Corresponding app/folder's name of the item. + std::string short_name; // Corresponding app's short name of the item. Empty + // if the app doesn't have one or it's a folder. + std::string folder_id; // Id of folder where the item resides. + syncer::StringOrdinal position; // Position of the item. + bool is_folder = false; // Whether this item is a folder. + bool is_persistent = false; // Whether this folder is allowed to contain only + // 1 item. + gfx::ImageSkia icon; // The icon of this item. + bool is_page_break = false; // Whether this item is a "page break" item. +}; + // All possible states of the app list. // Note: Do not change the order of these as they are used for metrics. enum class AppListState {
diff --git a/ash/public/interfaces/app_list.mojom b/ash/public/interfaces/app_list.mojom index 5527921..9f5fb1b 100644 --- a/ash/public/interfaces/app_list.mojom +++ b/ash/public/interfaces/app_list.mojom
@@ -13,23 +13,6 @@ import "ui/gfx/range/mojo/range.mojom"; import "url/mojom/url.mojom"; -// A structure holding the common information which is sent between ash and, -// chrome representing an app list item. -// This structure should be kept as small as possible so that minimum data -// is sent via mojo calls when an item is moved or reparented. -struct AppListItemMetadata { - string id; // The id of the app list item. - string name; // The corresponding app or folder's name of the item. - string short_name; // The corresponding app's short name of the item. It's - // empty if the app doesn't have one or it's a folder. - string folder_id; // The id of the item's folder. - syncer.mojom.StringOrdinal position; // The position of the item. - bool is_folder; // Whether this item is a folder. - bool is_persistent; // Whether this folder is allowed to contain 1 item. - gfx.mojom.ImageSkia? icon; // The icon of this item. - bool is_page_break; // Whether this item is a "page break" item. -}; - // A structure holding the common information which is sent from chrome to ash, // representing a search result. struct SearchResultMetadata {
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc index 869c940..73ebd5b 100644 --- a/ash/shelf/shelf_layout_manager_unittest.cc +++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -1344,7 +1344,7 @@ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState()); EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState()); EXPECT_EQ(display.bounds().bottom() - kHiddenShelfInScreenPortion, - GetShelfWidget()->GetWindowBoundsInScreen().y()); + GetShelfWidget()->GetNativeWindow()->GetTargetBounds().y()); } // Assertions around SetAutoHideBehavior.
diff --git a/ash/system/accessibility/accessibility_feature_disable_dialog.cc b/ash/system/accessibility/accessibility_feature_disable_dialog.cc index 90315799..6030ffc 100644 --- a/ash/system/accessibility/accessibility_feature_disable_dialog.cc +++ b/ash/system/accessibility/accessibility_feature_disable_dialog.cc
@@ -89,4 +89,8 @@ return weak_ptr_factory_.GetWeakPtr(); } +const char* AccessibilityFeatureDisableDialog::GetClassName() const { + return "AccessibilityFeatureDisableDialog"; +} + } // namespace ash \ No newline at end of file
diff --git a/ash/system/accessibility/accessibility_feature_disable_dialog.h b/ash/system/accessibility/accessibility_feature_disable_dialog.h index 60a8cc9..a33079a0 100644 --- a/ash/system/accessibility/accessibility_feature_disable_dialog.h +++ b/ash/system/accessibility/accessibility_feature_disable_dialog.h
@@ -34,6 +34,9 @@ base::WeakPtr<AccessibilityFeatureDisableDialog> GetWeakPtr(); + // views::View: + const char* GetClassName() const override; + private: const base::string16 window_title_; base::OnceClosure on_accept_callback_;
diff --git a/ash/system/accessibility/autoclick_menu_view.cc b/ash/system/accessibility/autoclick_menu_view.cc index 23651c9..668178f 100644 --- a/ash/system/accessibility/autoclick_menu_view.cc +++ b/ash/system/accessibility/autoclick_menu_view.cc
@@ -56,6 +56,9 @@ ~AutoclickMenuButton() override = default; + // views::Button: + const char* GetClassName() const override { return "AutoclickMenuButton"; } + // Set the vector icon shown in a circle. void SetVectorIcon(const gfx::VectorIcon& icon) { icon_ = &icon; @@ -137,6 +140,10 @@ SetAnchorRect(rect); } +const char* AutoclickMenuBubbleView::GetClassName() const { + return "AutoclickMenuBubbleView"; +} + // ------ AutoclickMenuView ------ // AutoclickMenuView::AutoclickMenuView(mojom::AutoclickEventType type, @@ -304,4 +311,8 @@ type); } +const char* AutoclickMenuView::GetClassName() const { + return "AutoclickMenuView"; +} + } // namespace ash
diff --git a/ash/system/accessibility/autoclick_menu_view.h b/ash/system/accessibility/autoclick_menu_view.h index 789ddec..5262bcb 100644 --- a/ash/system/accessibility/autoclick_menu_view.h +++ b/ash/system/accessibility/autoclick_menu_view.h
@@ -25,6 +25,9 @@ void MoveToPosition(const gfx::Rect& rect); + // views::View: + const char* GetClassName() const override; + private: DISALLOW_COPY_AND_ASSIGN(AutoclickMenuBubbleView); }; @@ -53,6 +56,9 @@ // views::ButtonListener: void ButtonPressed(views::Button* sender, const ui::Event& event) override; + // views::View: + const char* GetClassName() const override; + private: // Unowned. Owned by views hierarchy. AutoclickMenuButton* left_click_button_;
diff --git a/ash/system/accessibility/dictation_button_tray.cc b/ash/system/accessibility/dictation_button_tray.cc index d5bdc3c..b99fd70c 100644 --- a/ash/system/accessibility/dictation_button_tray.cc +++ b/ash/system/accessibility/dictation_button_tray.cc
@@ -78,6 +78,10 @@ // This class has no bubbles to hide. } +const char* DictationButtonTray::GetClassName() const { + return "DictationButtonTray"; +} + void DictationButtonTray::UpdateIcon(bool dictation_active) { if (dictation_active) { icon_->SetImage(on_image_);
diff --git a/ash/system/accessibility/dictation_button_tray.h b/ash/system/accessibility/dictation_button_tray.h index 9568d16..bf646c6 100644 --- a/ash/system/accessibility/dictation_button_tray.h +++ b/ash/system/accessibility/dictation_button_tray.h
@@ -46,6 +46,9 @@ base::string16 GetAccessibleNameForTray() override; void HideBubbleWithView(const TrayBubbleView* bubble_view) override; + // views::View: + const char* GetClassName() const override; + private: friend class DictationButtonTrayTest;
diff --git a/ash/system/accessibility/tray_accessibility.cc b/ash/system/accessibility/tray_accessibility.cc index 713891f..ba303d3f 100644 --- a/ash/system/accessibility/tray_accessibility.cc +++ b/ash/system/accessibility/tray_accessibility.cc
@@ -137,6 +137,10 @@ sticky_keys_enabled_); } +const char* AccessibilityDetailedView::GetClassName() const { + return "AccessibilityDetailedView"; +} + void AccessibilityDetailedView::AppendAccessibilityList() { CreateScrollableList();
diff --git a/ash/system/accessibility/tray_accessibility.h b/ash/system/accessibility/tray_accessibility.h index 03e26ee2..1eb765b 100644 --- a/ash/system/accessibility/tray_accessibility.h +++ b/ash/system/accessibility/tray_accessibility.h
@@ -42,6 +42,9 @@ void OnAccessibilityStatusChanged(); + // views::View + const char* GetClassName() const override; + private: friend class ::ash::TrayAccessibilityLoginScreenTest; friend class ::ash::TrayAccessibilityTest;
diff --git a/ash/system/audio/audio_detailed_view.cc b/ash/system/audio/audio_detailed_view.cc index 63ee464..9aab6993 100644 --- a/ash/system/audio/audio_detailed_view.cc +++ b/ash/system/audio/audio_detailed_view.cc
@@ -70,6 +70,10 @@ Layout(); } +const char* AudioDetailedView::GetClassName() const { + return "AudioDetailedView"; +} + void AudioDetailedView::AddAudioSubHeader(const gfx::VectorIcon& icon, int text_id) { TriView* header = AddScrollListSubHeader(icon, text_id);
diff --git a/ash/system/audio/audio_detailed_view.h b/ash/system/audio/audio_detailed_view.h index 67b240c1..e9203327 100644 --- a/ash/system/audio/audio_detailed_view.h +++ b/ash/system/audio/audio_detailed_view.h
@@ -26,6 +26,9 @@ void Update(); + // views::View: + const char* GetClassName() const override; + private: // Helper function to add non-clickable header rows within the scrollable // list.
diff --git a/ash/system/audio/unified_volume_view.cc b/ash/system/audio/unified_volume_view.cc index 739618df..d4f97e7 100644 --- a/ash/system/audio/unified_volume_view.cc +++ b/ash/system/audio/unified_volume_view.cc
@@ -120,6 +120,8 @@ kTrayItemSize / 2); } + const char* GetClassName() const override { return "MoreButton"; } + private: DISALLOW_COPY_AND_ASSIGN(MoreButton); }; @@ -140,6 +142,10 @@ CrasAudioHandler::Get()->RemoveAudioObserver(this); } +const char* UnifiedVolumeView::GetClassName() const { + return "UnifiedVolumeView"; +} + void UnifiedVolumeView::Update(bool by_user) { bool is_muted = CrasAudioHandler::Get()->IsOutputMuted(); float level = CrasAudioHandler::Get()->GetOutputVolumePercent() / 100.f;
diff --git a/ash/system/audio/unified_volume_view.h b/ash/system/audio/unified_volume_view.h index 69e2fba..dadbfd2f 100644 --- a/ash/system/audio/unified_volume_view.h +++ b/ash/system/audio/unified_volume_view.h
@@ -21,6 +21,9 @@ views::Button* more_button() { return more_button_; } + // views::View: + const char* GetClassName() const override; + private: void Update(bool by_user);
diff --git a/ash/system/bluetooth/bluetooth_detailed_view.cc b/ash/system/bluetooth/bluetooth_detailed_view.cc index 4271f36..eb2a182 100644 --- a/ash/system/bluetooth/bluetooth_detailed_view.cc +++ b/ash/system/bluetooth/bluetooth_detailed_view.cc
@@ -218,6 +218,10 @@ toggle_->AnimateIsOn(is_on); } +const char* BluetoothDetailedView::GetClassName() const { + return "BluetoothDetailedView"; +} + void BluetoothDetailedView::CreateItems() { CreateScrollableList(); CreateTitleRow(IDS_ASH_STATUS_TRAY_BLUETOOTH);
diff --git a/ash/system/bluetooth/bluetooth_detailed_view.h b/ash/system/bluetooth/bluetooth_detailed_view.h index 71769817c..2001148 100644 --- a/ash/system/bluetooth/bluetooth_detailed_view.h +++ b/ash/system/bluetooth/bluetooth_detailed_view.h
@@ -47,6 +47,9 @@ // Sets the state of the toggle in the header. void SetToggleIsOn(bool is_on); + // views::View: + const char* GetClassName() const override; + private: void CreateItems();
diff --git a/ash/system/brightness/unified_brightness_view.cc b/ash/system/brightness/unified_brightness_view.cc index fc60c2e3..3215fc3 100644 --- a/ash/system/brightness/unified_brightness_view.cc +++ b/ash/system/brightness/unified_brightness_view.cc
@@ -32,4 +32,8 @@ SetSliderValue(model_->display_brightness(), by_user); } +const char* UnifiedBrightnessView::GetClassName() const { + return "UnifiedBrightnessView"; +} + } // namespace ash
diff --git a/ash/system/brightness/unified_brightness_view.h b/ash/system/brightness/unified_brightness_view.h index 596574b0..8dcea58d 100644 --- a/ash/system/brightness/unified_brightness_view.h +++ b/ash/system/brightness/unified_brightness_view.h
@@ -24,6 +24,9 @@ // UnifiedSystemTrayModel::Observer: void OnDisplayBrightnessChanged(bool by_user) override; + // views::View: + const char* GetClassName() const override; + private: UnifiedSystemTrayModel* const model_;
diff --git a/ash/system/cast/tray_cast.cc b/ash/system/cast/tray_cast.cc index 07e3c7ec..e5aa7ac 100644 --- a/ash/system/cast/tray_cast.cc +++ b/ash/system/cast/tray_cast.cc
@@ -112,6 +112,10 @@ Layout(); } +const char* CastDetailedView::GetClassName() const { + return "CastDetailedView"; +} + void CastDetailedView::UpdateReceiverListFromCachedData() { // Remove all of the existing views. view_to_sink_map_.clear();
diff --git a/ash/system/cast/tray_cast.h b/ash/system/cast/tray_cast.h index 0c1d717..85435554 100644 --- a/ash/system/cast/tray_cast.h +++ b/ash/system/cast/tray_cast.h
@@ -27,6 +27,9 @@ // CastConfigController::Observer: void OnDevicesUpdated(const std::vector<SinkAndRoute>& devices) override; + // views::View: + const char* GetClassName() const override; + private: void CreateItems();
diff --git a/ash/system/ime_menu/ime_list_view.cc b/ash/system/ime_menu/ime_list_view.cc index 5bf5267..d621640 100644 --- a/ash/system/ime_menu/ime_list_view.cc +++ b/ash/system/ime_menu/ime_list_view.cc
@@ -306,8 +306,7 @@ std::string ime_id = ime->second; last_selected_item_id_ = ime_id; ime_controller->SwitchImeById(ime_id, false /* show_message */); - UMA_HISTOGRAM_ENUMERATION("InputMethod.ImeSwitch", ImeSwitchType::kTray, - ImeSwitchType::kCount); + UMA_HISTOGRAM_ENUMERATION("InputMethod.ImeSwitch", ImeSwitchType::kTray); } else { std::map<views::View*, std::string>::const_iterator property =
diff --git a/ash/system/locale/locale_detailed_view.cc b/ash/system/locale/locale_detailed_view.cc index 72df6a8..dbc14de 100644 --- a/ash/system/locale/locale_detailed_view.cc +++ b/ash/system/locale/locale_detailed_view.cc
@@ -91,6 +91,8 @@ ScrollViewToVisible(); } + const char* GetClassName() const override { return "LocaleItem"; } + void GetAccessibleNodeData(ui::AXNodeData* node_data) override { ActionableView::GetAccessibleNodeData(node_data); node_data->role = ax::mojom::Role::kCheckBox; @@ -148,5 +150,9 @@ } } +const char* LocaleDetailedView::GetClassName() const { + return "LocaleDetailedView"; +} + } // namespace tray } // namespace ash \ No newline at end of file
diff --git a/ash/system/locale/locale_detailed_view.h b/ash/system/locale/locale_detailed_view.h index 49fb7751..21c6bbfd 100644 --- a/ash/system/locale/locale_detailed_view.h +++ b/ash/system/locale/locale_detailed_view.h
@@ -23,6 +23,9 @@ // TrayDetailedView: void HandleViewClicked(views::View* view) override; + // views::View: + const char* GetClassName() const override; + private: void CreateItems();
diff --git a/ash/system/network/active_network_icon.cc b/ash/system/network/active_network_icon.cc index 1c4a604..42fc4263 100644 --- a/ash/system/network/active_network_icon.cc +++ b/ash/system/network/active_network_icon.cc
@@ -86,16 +86,6 @@ base::Unretained(this), connector)); } -base::string16 ActiveNetworkIcon::GetDefaultLabel( - network_icon::IconType icon_type) { - if (!default_network_) { - if (cellular_uninitialized_msg_ != 0) - return l10n_util::GetStringUTF16(cellular_uninitialized_msg_); - return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_NOT_CONNECTED); - } - return network_icon::GetLabelForNetwork(*default_network_, icon_type); -} - gfx::ImageSkia ActiveNetworkIcon::GetSingleImage( network_icon::IconType icon_type, bool* animating) {
diff --git a/ash/system/network/active_network_icon.h b/ash/system/network/active_network_icon.h index c9e3429..70904b5 100644 --- a/ash/system/network/active_network_icon.h +++ b/ash/system/network/active_network_icon.h
@@ -37,8 +37,8 @@ // a technology badge is used to represent the network. // ** Cellular (enabled devices only): The state of the Cellular connection if // available regardless of whether it is the active network. -// NOTE : GetSingleDefaultImage and GetDefaultLabel are partially tested in -// network_icon_unittest.cc, and partially in active_network_icon_unittest.cc. +// NOTE : GetSingleDefaultImage is partially tested in network_icon_unittest.cc, +// and partially in active_network_icon_unittest.cc. // TODO(stevenjb): Move all test coverage to active_network_icon_unittest.cc and // test Dual icon methods. // This class is also responsible for periodically purging the icon cache. @@ -48,9 +48,6 @@ explicit ActiveNetworkIcon(service_manager::Connector* connector); ~ActiveNetworkIcon() override; - // Returns the label for the primary active network.. - base::string16 GetDefaultLabel(network_icon::IconType icon_type); - // Single image mode. Returns a network icon (which may be empty) and sets // |animating| if provided. gfx::ImageSkia GetSingleImage(network_icon::IconType icon_type,
diff --git a/ash/system/network/active_network_icon_unittest.cc b/ash/system/network/active_network_icon_unittest.cc index 52cb2e5..a354f41 100644 --- a/ash/system/network/active_network_icon_unittest.cc +++ b/ash/system/network/active_network_icon_unittest.cc
@@ -166,24 +166,6 @@ DISALLOW_COPY_AND_ASSIGN(ActiveNetworkIconTest); }; -TEST_F(ActiveNetworkIconTest, GetDefaultLabel) { - SetupCellular(shill::kStateOnline); - base::string16 label = active_network_icon()->GetDefaultLabel(icon_type()); - // Note: The guid is used for the name in ConfigureService. - EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED, - base::UTF8ToUTF16("cellular_guid")), - label); - - SetupWiFi(shill::kStateIdle); - network_state_handler()->SetNetworkConnectRequested(wifi_path(), true); - base::RunLoop().RunUntilIdle(); - label = active_network_icon()->GetDefaultLabel(icon_type()); - // Note: The guid is used for the name in ConfigureService. - EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_CONNECTING, - base::UTF8ToUTF16("wifi_guid")), - label); -} - TEST_F(ActiveNetworkIconTest, GetSingleImage) { // Cellular only = Cellular icon SetupCellular(shill::kStateOnline); @@ -234,11 +216,6 @@ TEST_F(ActiveNetworkIconTest, CellularUninitialized) { SetCellularUninitialized(false /* scanning */); - base::string16 label = active_network_icon()->GetDefaultLabel(icon_type()); - EXPECT_EQ( - l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_INITIALIZING_CELLULAR), - label); - bool animating; gfx::ImageSkia image = active_network_icon()->GetSingleImage(icon_type(), &animating); @@ -254,10 +231,6 @@ ASSERT_TRUE(network_state_handler()->GetScanningByType( chromeos::NetworkTypePattern::Cellular())); - base::string16 label = active_network_icon()->GetDefaultLabel(icon_type()); - EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_MOBILE_SCANNING), - label); - bool animating; gfx::ImageSkia image = active_network_icon()->GetSingleImage(icon_type(), &animating);
diff --git a/ash/system/network/network_feature_pod_button.cc b/ash/system/network/network_feature_pod_button.cc index 9cc0c12a..03bac40 100644 --- a/ash/system/network/network_feature_pod_button.cc +++ b/ash/system/network/network_feature_pod_button.cc
@@ -187,6 +187,10 @@ Update(); } +const char* NetworkFeaturePodButton::GetClassName() const { + return "NetworkFeaturePodButton"; +} + void NetworkFeaturePodButton::Update() { bool animating = false; gfx::ImageSkia image =
diff --git a/ash/system/network/network_feature_pod_button.h b/ash/system/network/network_feature_pod_button.h index 49acdcb..52a5325 100644 --- a/ash/system/network/network_feature_pod_button.h +++ b/ash/system/network/network_feature_pod_button.h
@@ -26,6 +26,9 @@ // TrayNetworkStateObserver::Observer: void ActiveNetworkStateChanged() override; + // views::Button: + const char* GetClassName() const override; + private: void Update(); void SetTooltipState(const base::string16& tooltip_state);
diff --git a/ash/system/network/network_icon.cc b/ash/system/network/network_icon.cc index 4d4ac1c..564908e 100644 --- a/ash/system/network/network_icon.cc +++ b/ash/system/network/network_icon.cc
@@ -581,42 +581,17 @@ return CreateNetworkIconImage(icon, badges); } -base::string16 GetLabelForNetwork(const NetworkIconState& network, - IconType icon_type) { +base::string16 GetLabelForNetworkList(const NetworkIconState& network) { ActivationStateType activation_state = network.activation_state; - if (icon_type == ICON_TYPE_LIST || icon_type == ICON_TYPE_MENU_LIST) { - // Show "<network>: [Connecting|Activating]..." - if (icon_type != ICON_TYPE_MENU_LIST && IsConnecting(network)) { - return l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_LIST_CONNECTING, - base::UTF8ToUTF16(network.name)); - } - if (activation_state == ActivationStateType::kActivating) { - return l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_LIST_ACTIVATING, - base::UTF8ToUTF16(network.name)); - } - // Show "Activate <network>" in list view only. - if (activation_state == ActivationStateType::kNotActivated || - activation_state == ActivationStateType::kPartiallyActivated) { - return l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_NETWORK_LIST_ACTIVATE, - base::UTF8ToUTF16(network.name)); - } - } else { - // Show "[Connected to|Connecting to|Activating] <network>" (non-list view). - if (IsConnected(network)) { - return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED, - base::UTF8ToUTF16(network.name)); - } - if (IsConnecting(network)) { - return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_CONNECTING, - base::UTF8ToUTF16(network.name)); - } - if (activation_state == ActivationStateType::kActivating) { - return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_ACTIVATING, - base::UTF8ToUTF16(network.name)); - } + if (activation_state == ActivationStateType::kActivating) { + return l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_NETWORK_LIST_ACTIVATING, + base::UTF8ToUTF16(network.name)); + } + if (activation_state == ActivationStateType::kNotActivated || + activation_state == ActivationStateType::kPartiallyActivated) { + return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_LIST_ACTIVATE, + base::UTF8ToUTF16(network.name)); } // Otherwise just show the network name or 'Ethernet'.
diff --git a/ash/system/network/network_icon.h b/ash/system/network/network_icon.h index 4ff01b3..caca2edd 100644 --- a/ash/system/network/network_icon.h +++ b/ash/system/network/network_icon.h
@@ -107,10 +107,9 @@ ASH_EXPORT gfx::ImageSkia GetImageForNewWifiNetwork(SkColor icon_color, SkColor badge_color); -// Returns the label for |network| based on |icon_type|. |network| cannot be -// nullptr. -ASH_EXPORT base::string16 GetLabelForNetwork(const NetworkIconState&, - IconType icon_type); +// Returns the label for |network| when displayed in a list. +ASH_EXPORT base::string16 GetLabelForNetworkList( + const NetworkIconState& network); // Called periodically with the current list of network guids. Removes cached // entries that are no longer in the list.
diff --git a/ash/system/network/network_icon_unittest.cc b/ash/system/network/network_icon_unittest.cc index 01f69d6c..c57f397 100644 --- a/ash/system/network/network_icon_unittest.cc +++ b/ash/system/network/network_icon_unittest.cc
@@ -99,12 +99,8 @@ return GetImageForNonVirtualNetwork(network, false /* show_vpn_badge */); } - void GetDefaultNetworkImageAndLabel(IconType icon_type, - gfx::ImageSkia* image, - base::string16* label, - bool* animating) { - *image = active_network_icon_->GetSingleImage(icon_type, animating); - *label = active_network_icon_->GetDefaultLabel(icon_type); + gfx::ImageSkia GetDefaultNetworkImage(IconType icon_type, bool* animating) { + return active_network_icon_->GetSingleImage(icon_type, animating); } // The icon for a Tether network should be the same as one for a cellular @@ -236,18 +232,15 @@ EXPECT_EQ(SignalStrength::STRONG, GetSignalStrength(100)); } -TEST_F(NetworkIconTest, DefaultImageAndLabelWifiConnected) { +TEST_F(NetworkIconTest, DefaultImageWifiConnected) { // Set the Wifi service as connected. SetServiceProperty(wifi1_path(), shill::kSignalStrengthProperty, base::Value(45)); SetServiceProperty(wifi1_path(), shill::kStateProperty, base::Value(shill::kStateOnline)); - gfx::ImageSkia default_image; - base::string16 label; bool animating = false; - GetDefaultNetworkImageAndLabel(icon_type_, &default_image, &label, - &animating); + gfx::ImageSkia default_image = GetDefaultNetworkImage(icon_type_, &animating); ASSERT_FALSE(default_image.isNull()); EXPECT_FALSE(animating); @@ -258,18 +251,15 @@ gfx::Image(default_image), ImageForNetwork(reference_network.get()))); } -TEST_F(NetworkIconTest, DefaultImageAndLabelWifiConnecting) { +TEST_F(NetworkIconTest, DefaultImageWifiConnecting) { // Set the Wifi service as connected. SetServiceProperty(wifi1_path(), shill::kSignalStrengthProperty, base::Value(45)); SetServiceProperty(wifi1_path(), shill::kStateProperty, base::Value(shill::kStateAssociation)); - gfx::ImageSkia default_image; - base::string16 label; bool animating = false; - GetDefaultNetworkImageAndLabel(icon_type_, &default_image, &label, - &animating); + gfx::ImageSkia default_image = GetDefaultNetworkImage(icon_type_, &animating); ASSERT_FALSE(default_image.isNull()); EXPECT_TRUE(animating); @@ -286,7 +276,7 @@ // connected, but that is not always the case. For example, if the connected // wifi service has no Internet connectivity, cellular service will be selected // as default. -TEST_F(NetworkIconTest, DefaultImageAndLabelCellularDefaultWithWifiConnected) { +TEST_F(NetworkIconTest, DefaultImageCellularDefaultWithWifiConnected) { // Set both wifi and cellular networks in a connected state, but with wifi not // online - this should prompt fake shill manager implementation to prefer // cellular network over wifi. @@ -300,11 +290,8 @@ SetServiceProperty(cellular_path(), shill::kStateProperty, base::Value(shill::kStateOnline)); - gfx::ImageSkia default_image; - base::string16 label; bool animating = false; - GetDefaultNetworkImageAndLabel(icon_type_, &default_image, &label, - &animating); + gfx::ImageSkia default_image = GetDefaultNetworkImage(icon_type_, &animating); ASSERT_FALSE(default_image.isNull()); EXPECT_FALSE(animating); @@ -334,14 +321,11 @@ SetServiceProperty(wifi1_path(), shill::kStateProperty, base::Value(shill::kStateAssociation)); - gfx::ImageSkia default_image; - base::string16 label; - bool animating = false; // Verify that the default network is connecting icon for the initial default // network (even though the default network as reported by shill actually // changed). - GetDefaultNetworkImageAndLabel(icon_type_, &default_image, &label, - &animating); + bool animating = false; + gfx::ImageSkia default_image = GetDefaultNetworkImage(icon_type_, &animating); ASSERT_FALSE(default_image.isNull()); EXPECT_TRUE(animating); @@ -364,8 +348,7 @@ NetworkStatePropertiesPtr reference_network_2 = CreateStandaloneNetworkProperties("reference2", NetworkType::kCellular, ConnectionStateType::kOnline, 65); - GetDefaultNetworkImageAndLabel(icon_type_, &default_image, &label, - &animating); + default_image = GetDefaultNetworkImage(icon_type_, &animating); ASSERT_FALSE(default_image.isNull()); EXPECT_FALSE(animating); @@ -380,8 +363,7 @@ NetworkStatePropertiesPtr reference_network_3 = CreateStandaloneNetworkProperties("reference3", NetworkType::kWiFi, ConnectionStateType::kOnline, 45); - GetDefaultNetworkImageAndLabel(icon_type_, &default_image, &label, - &animating); + default_image = GetDefaultNetworkImage(icon_type_, &animating); ASSERT_FALSE(default_image.isNull()); EXPECT_FALSE(animating); @@ -405,11 +387,8 @@ SetServiceProperty(wifi1_path(), shill::kStateProperty, base::Value(shill::kStateIdle)); - gfx::ImageSkia default_image; - base::string16 label; bool animating = false; - GetDefaultNetworkImageAndLabel(icon_type_, &default_image, &label, - &animating); + gfx::ImageSkia default_image = GetDefaultNetworkImage(icon_type_, &animating); ASSERT_FALSE(default_image.isNull()); EXPECT_FALSE(animating); @@ -438,15 +417,12 @@ SetServiceProperty(cellular_path(), shill::kStateProperty, base::Value(shill::kStateAssociation)); - gfx::ImageSkia default_image; - base::string16 label; - bool animating = false; // Currently, a connecting icon is used as default network icon even if // another network connected and used as default. // TODO(tbarzic): Consider changing network icon logic to use a connected // network icon if a network is connected while a network is reconnecting. - GetDefaultNetworkImageAndLabel(icon_type_, &default_image, &label, - &animating); + bool animating = false; + gfx::ImageSkia default_image = GetDefaultNetworkImage(icon_type_, &animating); ASSERT_FALSE(default_image.isNull()); EXPECT_TRUE(animating); @@ -461,8 +437,7 @@ SetServiceProperty(cellular_path(), shill::kStateProperty, base::Value(shill::kStateReady)); - GetDefaultNetworkImageAndLabel(icon_type_, &default_image, &label, - &animating); + default_image = GetDefaultNetworkImage(icon_type_, &animating); ASSERT_FALSE(default_image.isNull()); EXPECT_FALSE(animating); NetworkStatePropertiesPtr reference_network_2 = @@ -476,8 +451,7 @@ SetServiceProperty(cellular_path(), shill::kStateProperty, base::Value(shill::kStateOnline)); - GetDefaultNetworkImageAndLabel(icon_type_, &default_image, &label, - &animating); + default_image = GetDefaultNetworkImage(icon_type_, &animating); ASSERT_FALSE(default_image.isNull()); EXPECT_FALSE(animating); EXPECT_TRUE(gfx::test::AreImagesEqual( @@ -498,11 +472,8 @@ SetServiceProperty(cellular_path(), shill::kStateProperty, base::Value(shill::kStateOnline)); - gfx::ImageSkia default_image; - base::string16 label; bool animating = false; - GetDefaultNetworkImageAndLabel(icon_type_, &default_image, &label, - &animating); + gfx::ImageSkia default_image = GetDefaultNetworkImage(icon_type_, &animating); ASSERT_FALSE(default_image.isNull()); EXPECT_FALSE(animating); @@ -521,11 +492,8 @@ SetServiceProperty(cellular_path(), shill::kActivationStateProperty, base::Value(shill::kActivationStateActivating)); - gfx::ImageSkia default_image; - base::string16 label; bool animating = false; - GetDefaultNetworkImageAndLabel(icon_type_, &default_image, &label, - &animating); + gfx::ImageSkia default_image = GetDefaultNetworkImage(icon_type_, &animating); ASSERT_FALSE(default_image.isNull()); EXPECT_FALSE(animating); @@ -550,11 +518,8 @@ SetServiceProperty(cellular_path(), shill::kActivationStateProperty, base::Value(shill::kActivationStateActivating)); - gfx::ImageSkia default_image; - base::string16 label; bool animating = false; - GetDefaultNetworkImageAndLabel(icon_type_, &default_image, &label, - &animating); + gfx::ImageSkia default_image = GetDefaultNetworkImage(icon_type_, &animating); ASSERT_FALSE(default_image.isNull()); EXPECT_FALSE(animating); @@ -567,10 +532,6 @@ // Tests VPN badging for the default network. TEST_F(NetworkIconTest, DefaultNetworkVpnBadge) { - gfx::ImageSkia default_image; - base::string16 label; - bool animating = false; - // Set up initial state with Ethernet and WiFi connected. std::string ethernet_path = ConfigureService( R"({"GUID": "ethernet_guid", "Type": "ethernet", "State": "online"})"); @@ -582,8 +543,8 @@ base::Value(45)); // With Ethernet and WiFi connected, the default icon should be empty. - GetDefaultNetworkImageAndLabel(icon_type_, &default_image, &label, - &animating); + bool animating = false; + gfx::ImageSkia default_image = GetDefaultNetworkImage(icon_type_, &animating); ASSERT_TRUE(default_image.isNull()); EXPECT_FALSE(animating); @@ -593,8 +554,7 @@ ASSERT_FALSE(vpn_path.empty()); // When a VPN is connected, the default icon should be Ethernet with a badge. - GetDefaultNetworkImageAndLabel(icon_type_, &default_image, &label, - &animating); + default_image = GetDefaultNetworkImage(icon_type_, &animating); ASSERT_FALSE(default_image.isNull()); EXPECT_FALSE(animating); @@ -613,8 +573,7 @@ // Disconnect Ethernet. The default icon should become WiFi with a badge. SetServiceProperty(ethernet_path, shill::kStateProperty, base::Value(shill::kStateIdle)); - GetDefaultNetworkImageAndLabel(icon_type_, &default_image, &label, - &animating); + default_image = GetDefaultNetworkImage(icon_type_, &animating); ASSERT_FALSE(default_image.isNull()); EXPECT_FALSE(animating); @@ -628,8 +587,7 @@ // Set the VPN to connecting; the default icon should be animating. SetServiceProperty(vpn_path, shill::kStateProperty, base::Value(shill::kStateAssociation)); - GetDefaultNetworkImageAndLabel(icon_type_, &default_image, &label, - &animating); + default_image = GetDefaultNetworkImage(icon_type_, &animating); ASSERT_FALSE(default_image.isNull()); EXPECT_TRUE(animating); } @@ -645,11 +603,8 @@ R"({"GUID": "vpn_guid", "Type": "vpn", "State": "online"})"); ASSERT_FALSE(vpn_path.empty()); - gfx::ImageSkia default_image; - base::string16 label; bool animating = false; - GetDefaultNetworkImageAndLabel(icon_type_, &default_image, &label, - &animating); + gfx::ImageSkia default_image = GetDefaultNetworkImage(icon_type_, &animating); ASSERT_FALSE(default_image.isNull()); EXPECT_TRUE(animating); @@ -672,11 +627,8 @@ R"({"GUID": "vpn_guid", "Type": "vpn", "State": "online"})"); ASSERT_FALSE(vpn_path.empty()); - gfx::ImageSkia default_image; - base::string16 label; bool animating = false; - GetDefaultNetworkImageAndLabel(icon_type_, &default_image, &label, - &animating); + gfx::ImageSkia default_image = GetDefaultNetworkImage(icon_type_, &animating); ASSERT_FALSE(default_image.isNull()); EXPECT_TRUE(animating);
diff --git a/ash/system/network/network_list.cc b/ash/system/network/network_list.cc index a52366599..0c520d2 100644 --- a/ash/system/network/network_list.cc +++ b/ash/system/network/network_list.cc
@@ -98,6 +98,10 @@ return true; } +const char* NetworkListView::GetClassName() const { + return "NetworkListView"; +} + void NetworkListView::BindCrosNetworkConfig() { // Ensure binding is reset in case this is called after a failure. cros_network_config_ptr_.reset(); @@ -160,8 +164,7 @@ auto info = std::make_unique<NetworkInfo>(network->guid); network_icon::NetworkIconState network_icon_state(network.get()); - info->label = network_icon::GetLabelForNetwork( - network_icon_state, network_icon::ICON_TYPE_MENU_LIST); + info->label = network_icon::GetLabelForNetworkList(network_icon_state); // |network_list_| only contains non virtual networks. info->image = network_icon::GetImageForNonVirtualNetwork( network_icon_state, network_icon::ICON_TYPE_LIST,
diff --git a/ash/system/network/network_list.h b/ash/system/network/network_list.h index da69afd..3943745 100644 --- a/ash/system/network/network_list.h +++ b/ash/system/network/network_list.h
@@ -45,6 +45,9 @@ void UpdateNetworkList() override; bool IsNetworkEntry(views::View* view, std::string* guid) const override; + // views::View: + const char* GetClassName() const override; + private: void BindCrosNetworkConfig(); void OnGetDeviceStateList(
diff --git a/ash/system/network/network_row_title_view.cc b/ash/system/network/network_row_title_view.cc index caf5089..4a8d6f8 100644 --- a/ash/system/network/network_row_title_view.cc +++ b/ash/system/network/network_row_title_view.cc
@@ -33,4 +33,9 @@ } NetworkRowTitleView::~NetworkRowTitleView() = default; + +const char* NetworkRowTitleView::GetClassName() const { + return "NetworkRowTitleView"; +} + } // namespace ash
diff --git a/ash/system/network/network_row_title_view.h b/ash/system/network/network_row_title_view.h index 21e64571..7ce2480 100644 --- a/ash/system/network/network_row_title_view.h +++ b/ash/system/network/network_row_title_view.h
@@ -17,6 +17,9 @@ explicit NetworkRowTitleView(int title_message_id); ~NetworkRowTitleView() override; + // views::View: + const char* GetClassName() const override; + private: views::Label* const title_;
diff --git a/ash/system/network/network_section_header_view.cc b/ash/system/network/network_section_header_view.cc index a4ffc7fa..9acddbf 100644 --- a/ash/system/network/network_section_header_view.cc +++ b/ash/system/network/network_section_header_view.cc
@@ -86,6 +86,10 @@ toggle_->AnimateIsOn(is_on); } +const char* NetworkSectionHeaderView::GetClassName() const { + return "NetworkSectionHeaderView"; +} + int NetworkSectionHeaderView::GetHeightForWidth(int width) const { // Make row height fixed avoiding layout manager adjustments. return GetPreferredSize().height();
diff --git a/ash/system/network/network_section_header_view.h b/ash/system/network/network_section_header_view.h index a385003..36367db 100644 --- a/ash/system/network/network_section_header_view.h +++ b/ash/system/network/network_section_header_view.h
@@ -33,6 +33,9 @@ // Modify enabled/disabled and on/off state of toggle. virtual void SetToggleState(bool toggle_enabled, bool is_on); + // views::View: + const char* GetClassName() const override; + protected: void Init(bool enabled);
diff --git a/ash/system/network/network_state_list_detailed_view.cc b/ash/system/network/network_state_list_detailed_view.cc index ec69d3b..348fab7b 100644 --- a/ash/system/network/network_state_list_detailed_view.cc +++ b/ash/system/network/network_state_list_detailed_view.cc
@@ -203,6 +203,10 @@ ToggleInfoBubble(); } +const char* NetworkStateListDetailedView::GetClassName() const { + return "NetworkStateListDetailedView"; +} + void NetworkStateListDetailedView::Init() { CreateScrollableList(); CreateTitleRow(list_type_ == ListType::LIST_TYPE_NETWORK
diff --git a/ash/system/network/network_state_list_detailed_view.h b/ash/system/network/network_state_list_detailed_view.h index 961683d..aee47d28 100644 --- a/ash/system/network/network_state_list_detailed_view.h +++ b/ash/system/network/network_state_list_detailed_view.h
@@ -36,6 +36,9 @@ void ToggleInfoBubbleForTesting(); + // views::View: + const char* GetClassName() const override; + protected: enum ListType { LIST_TYPE_NETWORK, LIST_TYPE_VPN };
diff --git a/ash/system/network/vpn_list_view.cc b/ash/system/network/vpn_list_view.cc index f6ec4b40..bb6a0fb 100644 --- a/ash/system/network/vpn_list_view.cc +++ b/ash/system/network/vpn_list_view.cc
@@ -130,6 +130,9 @@ tri_view->AddView(TriView::Container::END, add_vpn_button); } + // views::View: + const char* GetClassName() const override { return "VPNListProviderEntry"; } + protected: // views::ButtonListener: void ButtonPressed(views::Button* sender, const ui::Event& event) override { @@ -175,6 +178,9 @@ // views::ButtonListener: void ButtonPressed(Button* sender, const ui::Event& event) override; + // views::View: + const char* GetClassName() const override { return "VPNListNetworkEntry"; } + private: void OnGetNetworkState(NetworkStatePropertiesPtr result); void UpdateFromNetworkState(const NetworkStateProperties* network); @@ -240,8 +246,7 @@ network_icon::NetworkIconState vpn_icon_state(vpn); gfx::ImageSkia image = network_icon::GetImageForVPN( vpn_icon_state, network_icon::ICON_TYPE_LIST); - base::string16 label = network_icon::GetLabelForNetwork( - vpn_icon_state, network_icon::ICON_TYPE_MENU_LIST); + base::string16 label = network_icon::GetLabelForNetworkList(vpn_icon_state); AddIconAndLabel(image, label); if (chromeos::network_config::StateIsConnected(vpn->connection_state)) { owner_->SetupConnectedScrollListItem(this); @@ -363,6 +368,10 @@ PrefRegistry::PUBLIC); } +const char* VPNListView::GetClassName() const { + return "VPNListView"; +} + void VPNListView::BindCrosNetworkConfig() { // Ensure binding is reset in case this is called after a failure. cros_network_config_ptr_.reset();
diff --git a/ash/system/network/vpn_list_view.h b/ash/system/network/vpn_list_view.h index 4ff980da..55bee4b 100644 --- a/ash/system/network/vpn_list_view.h +++ b/ash/system/network/vpn_list_view.h
@@ -59,6 +59,9 @@ // See Shell::RegisterProfilePrefs(). static void RegisterProfilePrefs(PrefRegistrySimple* registry); + // views::View: + const char* GetClassName() const override; + private: using NetworkStateList = std::vector<chromeos::network_config::mojom::NetworkStatePropertiesPtr>;
diff --git a/ash/system/night_light/night_light_toggle_button.cc b/ash/system/night_light/night_light_toggle_button.cc index 3bdcdcb..cc3974a0 100644 --- a/ash/system/night_light/night_light_toggle_button.cc +++ b/ash/system/night_light/night_light_toggle_button.cc
@@ -60,6 +60,10 @@ NotifyAccessibilityEvent(ax::mojom::Event::kAriaAttributeChanged, true); } +const char* NightLightToggleButton::GetClassName() const { + return "NightLightToggleButton"; +} + void NightLightToggleButton::Update() { const bool night_light_enabled = Shell::Get()->night_light_controller()->GetEnabled();
diff --git a/ash/system/night_light/night_light_toggle_button.h b/ash/system/night_light/night_light_toggle_button.h index 5f9bdcd..696e40c 100644 --- a/ash/system/night_light/night_light_toggle_button.h +++ b/ash/system/night_light/night_light_toggle_button.h
@@ -19,6 +19,9 @@ // Toggles the status of NightLight. void Toggle(); + // views::View: + const char* GetClassName() const override; + private: // Updates the icon and its style based on the status of NightLight. void Update();
diff --git a/ash/system/overview/overview_button_tray.cc b/ash/system/overview/overview_button_tray.cc index 134c511..639bed0 100644 --- a/ash/system/overview/overview_button_tray.cc +++ b/ash/system/overview/overview_button_tray.cc
@@ -168,6 +168,10 @@ // This class has no bubbles to hide. } +const char* OverviewButtonTray::GetClassName() const { + return "OverviewButtonTray"; +} + void OverviewButtonTray::UpdateIconVisibility() { // The visibility of the OverviewButtonTray has diverged from // OverviewController::CanSelect. The visibility of the button should
diff --git a/ash/system/overview/overview_button_tray.h b/ash/system/overview/overview_button_tray.h index bf6419e..7669961 100644 --- a/ash/system/overview/overview_button_tray.h +++ b/ash/system/overview/overview_button_tray.h
@@ -69,6 +69,9 @@ base::string16 GetAccessibleNameForTray() override; void HideBubbleWithView(const TrayBubbleView* bubble_view) override; + // views::View: + const char* GetClassName() const override; + private: friend class OverviewButtonTrayTest;
diff --git a/ash/system/power/power_button_menu_item_view.cc b/ash/system/power/power_button_menu_item_view.cc index a514363..3c944267c 100644 --- a/ash/system/power/power_button_menu_item_view.cc +++ b/ash/system/power/power_button_menu_item_view.cc
@@ -72,6 +72,10 @@ PowerButtonMenuItemView::~PowerButtonMenuItemView() = default; +const char* PowerButtonMenuItemView::GetClassName() const { + return "PowerButtonMenuItemView"; +} + void PowerButtonMenuItemView::Layout() { const gfx::Rect rect(GetContentsBounds());
diff --git a/ash/system/power/power_button_menu_item_view.h b/ash/system/power/power_button_menu_item_view.h index 22e9277..4464bd7 100644 --- a/ash/system/power/power_button_menu_item_view.h +++ b/ash/system/power/power_button_menu_item_view.h
@@ -38,6 +38,9 @@ const base::string16& title_text); ~PowerButtonMenuItemView() override; + // views::View: + const char* GetClassName() const override; + private: // views::View: void Layout() override;
diff --git a/ash/system/power/power_button_menu_screen_view.cc b/ash/system/power/power_button_menu_screen_view.cc index 38354c1..0d7cd8c 100644 --- a/ash/system/power/power_button_menu_screen_view.cc +++ b/ash/system/power/power_button_menu_screen_view.cc
@@ -96,6 +96,11 @@ layer()->SetOpacity(show ? kPowerButtonMenuOpacity : 0.f); } + // views::View: + const char* GetClassName() const override { + return "PowerButtonMenuScreenView"; + } + private: // A callback for when the animation that shows the power menu has finished. base::RepeatingClosure show_animation_done_; @@ -132,6 +137,10 @@ power_button_menu_view_->ScheduleShowHideAnimation(show); } +const char* PowerButtonMenuScreenView::GetClassName() const { + return "PowerButtonMenuScreenView"; +} + void PowerButtonMenuScreenView::Layout() { power_button_screen_background_shield_->SetBoundsRect(GetContentsBounds());
diff --git a/ash/system/power/power_button_menu_screen_view.h b/ash/system/power/power_button_menu_screen_view.h index 9f1a8721..0c2fe78 100644 --- a/ash/system/power/power_button_menu_screen_view.h +++ b/ash/system/power/power_button_menu_screen_view.h
@@ -38,6 +38,9 @@ // Schedules an animation to show or hide the view. void ScheduleShowHideAnimation(bool show); + // views::View: + const char* GetClassName() const override; + private: class PowerButtonMenuBackgroundView;
diff --git a/ash/system/power/power_button_menu_view.cc b/ash/system/power/power_button_menu_view.cc index 246f530..683ef05 100644 --- a/ash/system/power/power_button_menu_view.cc +++ b/ash/system/power/power_button_menu_view.cc
@@ -137,6 +137,10 @@ return transform_displacement; } +const char* PowerButtonMenuView::GetClassName() const { + return "PowerButtonMenuView"; +} + void PowerButtonMenuView::CreateItems() { power_off_item_ = new PowerButtonMenuItemView( this, kSystemPowerButtonMenuPowerOffIcon,
diff --git a/ash/system/power/power_button_menu_view.h b/ash/system/power/power_button_menu_view.h index 8e0a645..5c94e3bd 100644 --- a/ash/system/power/power_button_menu_view.h +++ b/ash/system/power/power_button_menu_view.h
@@ -70,6 +70,9 @@ // Gets the transform displacement, which contains direction and distance. TransformDisplacement GetTransformDisplacement() const; + // views::View: + const char* GetClassName() const override; + private: // Creates the items that in the menu. void CreateItems();
diff --git a/ash/system/power/power_status_view.cc b/ash/system/power/power_status_view.cc index f579a54..98dc68b 100644 --- a/ash/system/power/power_status_view.cc +++ b/ash/system/power/power_status_view.cc
@@ -94,4 +94,8 @@ node_data->SetName(accessible_name_); } +const char* PowerStatusView::GetClassName() const { + return "PowerStatusView"; +} + } // namespace ash
diff --git a/ash/system/power/power_status_view.h b/ash/system/power/power_status_view.h index e7ee96cb..c603576 100644 --- a/ash/system/power/power_status_view.h +++ b/ash/system/power/power_status_view.h
@@ -26,6 +26,7 @@ // views::View: void Layout() override; void GetAccessibleNodeData(ui::AXNodeData* node_data) override; + const char* GetClassName() const override; // PowerStatus::Observer: void OnPowerStatusChanged() override;
diff --git a/ash/system/power/tray_power.cc b/ash/system/power/tray_power.cc index ce909be..ed90bf1f 100644 --- a/ash/system/power/tray_power.cc +++ b/ash/system/power/tray_power.cc
@@ -73,6 +73,10 @@ return tooltip_; } +const char* PowerTrayView::GetClassName() const { + return "PowerTrayView"; +} + void PowerTrayView::OnPowerStatusChanged() { UpdateStatus(); }
diff --git a/ash/system/power/tray_power.h b/ash/system/power/tray_power.h index 2b199652..dd614e6 100644 --- a/ash/system/power/tray_power.h +++ b/ash/system/power/tray_power.h
@@ -29,6 +29,7 @@ void GetAccessibleNodeData(ui::AXNodeData* node_data) override; views::View* GetTooltipHandlerForPoint(const gfx::Point& point) override; base::string16 GetTooltipText(const gfx::Point& p) const override; + const char* GetClassName() const override; // PowerStatus::Observer: void OnPowerStatusChanged() override;
diff --git a/ash/system/session/logout_button_tray.cc b/ash/system/session/logout_button_tray.cc index 291dc3a..25faeea3 100644 --- a/ash/system/session/logout_button_tray.cc +++ b/ash/system/session/logout_button_tray.cc
@@ -108,6 +108,10 @@ node_data->SetName(button_->GetText()); } +const char* LogoutButtonTray::GetClassName() const { + return "LogoutButtonTray"; +} + void LogoutButtonTray::UpdateShowLogoutButtonInTray() { show_logout_button_in_tray_ = pref_change_registrar_->prefs()->GetBoolean( prefs::kShowLogoutButtonInTray);
diff --git a/ash/system/session/logout_button_tray.h b/ash/system/session/logout_button_tray.h index 7601a50..be52a416 100644 --- a/ash/system/session/logout_button_tray.h +++ b/ash/system/session/logout_button_tray.h
@@ -41,6 +41,7 @@ // views::View: void GetAccessibleNodeData(ui::AXNodeData* node_data) override; + const char* GetClassName() const override; // views::ButtonListener: void ButtonPressed(views::Button* sender, const ui::Event& event) override;
diff --git a/ash/system/session/logout_confirmation_dialog.cc b/ash/system/session/logout_confirmation_dialog.cc index 643025a..e1a5e87 100644 --- a/ash/system/session/logout_confirmation_dialog.cc +++ b/ash/system/session/logout_confirmation_dialog.cc
@@ -112,6 +112,10 @@ GetLayoutManager()->GetPreferredHeightForWidth(this, kDefaultWidth)); } +const char* LogoutConfirmationDialog::GetClassName() const { + return "LogoutConfirmationDialog"; +} + void LogoutConfirmationDialog::UpdateLabel() { const base::TimeDelta time_remaining = logout_time_ - controller_->clock()->NowTicks();
diff --git a/ash/system/session/logout_confirmation_dialog.h b/ash/system/session/logout_confirmation_dialog.h index 74e9832..c395f3f 100644 --- a/ash/system/session/logout_confirmation_dialog.h +++ b/ash/system/session/logout_confirmation_dialog.h
@@ -44,6 +44,7 @@ // views::View: gfx::Size CalculatePreferredSize() const override; + const char* GetClassName() const override; private: void UpdateLabel();
diff --git a/ash/system/time/time_tray_item_view.cc b/ash/system/time/time_tray_item_view.cc index 6ec8e4cf..24800637 100644 --- a/ash/system/time/time_tray_item_view.cc +++ b/ash/system/time/time_tray_item_view.cc
@@ -40,5 +40,9 @@ time_view_->SetTextColorBasedOnSession(state); } +const char* TimeTrayItemView::GetClassName() const { + return "TimeTrayItemView"; +} + } // namespace tray } // namespace ash
diff --git a/ash/system/time/time_tray_item_view.h b/ash/system/time/time_tray_item_view.h index 4e203ab0..53a1b9e 100644 --- a/ash/system/time/time_tray_item_view.h +++ b/ash/system/time/time_tray_item_view.h
@@ -28,6 +28,9 @@ // SessionObserver: void OnSessionStateChanged(session_manager::SessionState state) override; + // views::View: + const char* GetClassName() const override; + private: TimeView* time_view_ = nullptr; ScopedSessionObserver session_observer_;
diff --git a/ash/system/time/time_view.cc b/ash/system/time/time_view.cc index cbc5196..767a0b3 100644 --- a/ash/system/time/time_view.cc +++ b/ash/system/time/time_view.cc
@@ -126,6 +126,10 @@ return model_->hour_clock_type(); } +const char* TimeView::GetClassName() const { + return "TimeView"; +} + bool TimeView::PerformAction(const ui::Event& event) { return false; }
diff --git a/ash/system/time/time_view.h b/ash/system/time/time_view.h index 01ccad2..c211b7bf 100644 --- a/ash/system/time/time_view.h +++ b/ash/system/time/time_view.h
@@ -56,6 +56,9 @@ base::HourClockType GetHourTypeForTesting() const; + // views::View: + const char* GetClassName() const override; + private: friend class TimeViewTest;
diff --git a/ash/system/tray/hover_highlight_view.cc b/ash/system/tray/hover_highlight_view.cc index a083c9e..a25f0f1 100644 --- a/ash/system/tray/hover_highlight_view.cc +++ b/ash/system/tray/hover_highlight_view.cc
@@ -229,6 +229,10 @@ node_data->SetCheckedState(checked_state); } +const char* HoverHighlightView::GetClassName() const { + return "HoverHighlightView"; +} + gfx::Size HoverHighlightView::CalculatePreferredSize() const { gfx::Size size = ActionableView::CalculatePreferredSize();
diff --git a/ash/system/tray/hover_highlight_view.h b/ash/system/tray/hover_highlight_view.h index d24a0329..1269161 100644 --- a/ash/system/tray/hover_highlight_view.h +++ b/ash/system/tray/hover_highlight_view.h
@@ -105,6 +105,7 @@ // views::View: void GetAccessibleNodeData(ui::AXNodeData* node_data) override; + const char* GetClassName() const override; TriView* tri_view() { return tri_view_; }
diff --git a/ash/system/tray/label_tray_view.cc b/ash/system/tray/label_tray_view.cc index f944891..bdadf25 100644 --- a/ash/system/tray/label_tray_view.cc +++ b/ash/system/tray/label_tray_view.cc
@@ -39,6 +39,10 @@ } } +const char* LabelTrayView::GetClassName() const { + return "LabelTrayView"; +} + views::View* LabelTrayView::CreateChildView( const base::string16& message) const { HoverHighlightView* child = new HoverHighlightView(click_listener_);
diff --git a/ash/system/tray/label_tray_view.h b/ash/system/tray/label_tray_view.h index cb8346e92..a97f834f 100644 --- a/ash/system/tray/label_tray_view.h +++ b/ash/system/tray/label_tray_view.h
@@ -29,6 +29,9 @@ void SetMessage(const base::string16& message); + // views::View: + const char* GetClassName() const override; + private: views::View* CreateChildView(const base::string16& message) const;
diff --git a/ash/system/tray/system_menu_button.cc b/ash/system/tray/system_menu_button.cc index eb86c61c..0bc09dc 100644 --- a/ash/system/tray/system_menu_button.cc +++ b/ash/system/tray/system_menu_button.cc
@@ -91,4 +91,8 @@ ink_drop_color_.value_or(kTrayPopupInkDropBaseColor)); } +const char* SystemMenuButton::GetClassName() const { + return "SystemMenuButton"; +} + } // namespace ash
diff --git a/ash/system/tray/system_menu_button.h b/ash/system/tray/system_menu_button.h index 2eccad49..0d2880f 100644 --- a/ash/system/tray/system_menu_button.h +++ b/ash/system/tray/system_menu_button.h
@@ -50,6 +50,7 @@ std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override; std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight() const override; + const char* GetClassName() const override; private: // Returns the size that the ink drop should be constructed with.
diff --git a/ash/system/tray/tray_bubble_view.cc b/ash/system/tray/tray_bubble_view.cc index 4e982f1..3263c17 100644 --- a/ash/system/tray/tray_bubble_view.cc +++ b/ash/system/tray/tray_bubble_view.cc
@@ -468,6 +468,10 @@ } } +const char* TrayBubbleView::GetClassName() const { + return "TrayBubbleView"; +} + void TrayBubbleView::MouseMovedOutOfHost() { // The user moved the mouse that was over the bubble when it was first shown. if (delegate_)
diff --git a/ash/system/tray/tray_bubble_view.h b/ash/system/tray/tray_bubble_view.h index cffe486..122f8f5 100644 --- a/ash/system/tray/tray_bubble_view.h +++ b/ash/system/tray/tray_bubble_view.h
@@ -172,6 +172,7 @@ void OnMouseEntered(const ui::MouseEvent& event) override; void OnMouseExited(const ui::MouseEvent& event) override; void GetAccessibleNodeData(ui::AXNodeData* node_data) override; + const char* GetClassName() const override; // Overridden from MouseWatcherListener void MouseMovedOutOfHost() override;
diff --git a/ash/system/tray/tray_container.cc b/ash/system/tray/tray_container.cc index 1cf11a4..137231b9 100644 --- a/ash/system/tray/tray_container.cc +++ b/ash/system/tray/tray_container.cc
@@ -60,6 +60,10 @@ return GetBoundsInScreen(); } +const char* TrayContainer::GetClassName() const { + return "TrayContainer"; +} + void TrayContainer::UpdateLayout() { const bool is_horizontal = shelf_->IsHorizontalAlignment();
diff --git a/ash/system/tray/tray_container.h b/ash/system/tray/tray_container.h index 1758e722..4495bbb 100644 --- a/ash/system/tray/tray_container.h +++ b/ash/system/tray/tray_container.h
@@ -29,6 +29,7 @@ void ViewHierarchyChanged( const views::ViewHierarchyChangedDetails& details) override; gfx::Rect GetAnchorBoundsInScreen() const override; + const char* GetClassName() const override; private: void UpdateLayout();
diff --git a/ash/system/tray/tray_detailed_view.cc b/ash/system/tray/tray_detailed_view.cc index 89e2e58..6a840da 100644 --- a/ash/system/tray/tray_detailed_view.cc +++ b/ash/system/tray/tray_detailed_view.cc
@@ -123,6 +123,8 @@ PositionHeaderRows(); } + const char* GetClassName() const override { return "ScrollContentsView"; } + View::Views GetChildrenInZOrder() override { // Place sticky headers last in the child order so that they wind up on top // in Z order. @@ -459,4 +461,8 @@ return height(); } +const char* TrayDetailedView::GetClassName() const { + return "TrayDetailedView"; +} + } // namespace ash
diff --git a/ash/system/tray/tray_detailed_view.h b/ash/system/tray/tray_detailed_view.h index f0ec573b..523581d1 100644 --- a/ash/system/tray/tray_detailed_view.h +++ b/ash/system/tray/tray_detailed_view.h
@@ -52,6 +52,7 @@ // views::View: void Layout() override; int GetHeightForWidth(int width) const override; + const char* GetClassName() const override; // Exposes the layout manager of this view to give control to subclasses. views::BoxLayout* box_layout() { return box_layout_; }
diff --git a/ash/system/tray/tray_info_label.cc b/ash/system/tray/tray_info_label.cc index c1c75cf..534fed4 100644 --- a/ash/system/tray/tray_info_label.cc +++ b/ash/system/tray/tray_info_label.cc
@@ -75,6 +75,10 @@ node_data->role = ax::mojom::Role::kLabelText; } +const char* TrayInfoLabel::GetClassName() const { + return "TrayInfoLabel"; +} + bool TrayInfoLabel::IsClickable() { if (delegate_) return delegate_->IsLabelClickable(message_id_);
diff --git a/ash/system/tray/tray_info_label.h b/ash/system/tray/tray_info_label.h index 5e7e631..f93d284 100644 --- a/ash/system/tray/tray_info_label.h +++ b/ash/system/tray/tray_info_label.h
@@ -40,6 +40,9 @@ bool PerformAction(const ui::Event& event) override; void GetAccessibleNodeData(ui::AXNodeData* node_data) override; + // views::View: + const char* GetClassName() const override; + private: friend class TrayInfoLabelTest;
diff --git a/ash/system/tray/tray_item_view.cc b/ash/system/tray/tray_item_view.cc index 6338d58e..f16a046 100644 --- a/ash/system/tray/tray_item_view.cc +++ b/ash/system/tray/tray_item_view.cc
@@ -110,6 +110,10 @@ return GetPreferredSize().height(); } +const char* TrayItemView::GetClassName() const { + return "TrayItemView"; +} + void TrayItemView::ChildPreferredSizeChanged(views::View* child) { PreferredSizeChanged(); }
diff --git a/ash/system/tray/tray_item_view.h b/ash/system/tray/tray_item_view.h index 596c76f..4973ef14 100644 --- a/ash/system/tray/tray_item_view.h +++ b/ash/system/tray/tray_item_view.h
@@ -62,6 +62,7 @@ void SetVisible(bool visible) override; gfx::Size CalculatePreferredSize() const override; int GetHeightForWidth(int width) const override; + const char* GetClassName() const override; protected: // The default animation duration is 200ms. But each view can customize this.
diff --git a/ash/system/virtual_keyboard/virtual_keyboard_tray.cc b/ash/system/virtual_keyboard/virtual_keyboard_tray.cc index 36ff6cc..fc0f311 100644 --- a/ash/system/virtual_keyboard/virtual_keyboard_tray.cc +++ b/ash/system/virtual_keyboard/virtual_keyboard_tray.cc
@@ -106,6 +106,10 @@ UpdateIcon(); } +const char* VirtualKeyboardTray::GetClassName() const { + return "VirtualKeyboardTray"; +} + void VirtualKeyboardTray::UpdateIcon() { const gfx::VectorIcon& icon = kShelfKeyboardNewuiIcon; gfx::ImageSkia image = gfx::CreateVectorIcon(
diff --git a/ash/system/virtual_keyboard/virtual_keyboard_tray.h b/ash/system/virtual_keyboard/virtual_keyboard_tray.h index b97aefa5..3ebfc15f 100644 --- a/ash/system/virtual_keyboard/virtual_keyboard_tray.h +++ b/ash/system/virtual_keyboard/virtual_keyboard_tray.h
@@ -43,6 +43,9 @@ // SessionObserver: void OnSessionStateChanged(session_manager::SessionState state) override; + // views::View: + const char* GetClassName() const override; + private: // Updates the icon UI. void UpdateIcon();
diff --git a/base/mac/foundation_util.h b/base/mac/foundation_util.h index d7f709d..7ddecaa 100644 --- a/base/mac/foundation_util.h +++ b/base/mac/foundation_util.h
@@ -402,6 +402,13 @@ #if defined(__OBJC__) BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, id); BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, NSRange); +BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, SEL); + +#if !defined(OS_IOS) +BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, NSPoint); +BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, NSRect); +BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, NSSize); +#endif #endif #endif // BASE_MAC_FOUNDATION_UTIL_H_
diff --git a/base/mac/foundation_util.mm b/base/mac/foundation_util.mm index b5003fbf..8b20ebc6 100644 --- a/base/mac/foundation_util.mm +++ b/base/mac/foundation_util.mm
@@ -510,3 +510,19 @@ std::ostream& operator<<(std::ostream& o, NSRange range) { return o << NSStringFromRange(range); } + +std::ostream& operator<<(std::ostream& o, SEL selector) { + return o << NSStringFromSelector(selector); +} + +#if !defined(OS_IOS) +std::ostream& operator<<(std::ostream& o, NSPoint point) { + return o << NSStringFromPoint(point); +} +std::ostream& operator<<(std::ostream& o, NSRect rect) { + return o << NSStringFromRect(rect); +} +std::ostream& operator<<(std::ostream& o, NSSize size) { + return o << NSStringFromSize(size); +} +#endif
diff --git a/base/win/scoped_variant.cc b/base/win/scoped_variant.cc index dc2374c1..61f645a 100644 --- a/base/win/scoped_variant.cc +++ b/base/win/scoped_variant.cc
@@ -95,24 +95,18 @@ ULONG flags = ignore_case ? NORM_IGNORECASE : 0; HRESULT hr = ::VarCmp(const_cast<VARIANT*>(&var_), const_cast<VARIANT*>(&var), LOCALE_USER_DEFAULT, flags); - int ret = 0; + DCHECK(SUCCEEDED(hr) && hr != VARCMP_NULL) + << "unsupported variant comparison: " << var_.vt << " and " << var.vt; switch (hr) { case VARCMP_LT: - ret = -1; - break; - + return -1; case VARCMP_GT: case VARCMP_NULL: - ret = 1; - break; - + return 1; default: - // Equal. - break; + return 0; } - - return ret; } void ScopedVariant::Set(const wchar_t* str) {
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index d48a2856..cadf9057 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -8912934291927162032 \ No newline at end of file +8912909845839913648 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 06cf694..4ccb055 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -8912948016361816848 \ No newline at end of file +8912928491539290416 \ No newline at end of file
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index 0ccf3592..ebb49824 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -856,11 +856,12 @@ _stamp_file, ] + _old_versions_dir = + "$root_out_dir/$chrome_product_full_name.app/Contents/Versions" if (new_mac_bundle_structure) { _versions_dir = "$root_out_dir/$chrome_product_full_name.app/Contents/Frameworks/$chrome_framework_name.framework/Versions" } else { - _versions_dir = - "$root_out_dir/$chrome_product_full_name.app/Contents/Versions" + _versions_dir = _old_versions_dir } args = [ @@ -876,6 +877,8 @@ args += [ "--keep", "Current", + "--delete", + rebase_path(_old_versions_dir, root_build_dir), ] } }
diff --git a/chrome/VERSION b/chrome/VERSION index 6cb0cf7..4945942 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=76 MINOR=0 -BUILD=3801 +BUILD=3802 PATCH=0
diff --git a/chrome/app/onboarding_welcome_strings.grdp b/chrome/app/onboarding_welcome_strings.grdp index eb5f4cc8..cbabb3c 100644 --- a/chrome/app/onboarding_welcome_strings.grdp +++ b/chrome/app/onboarding_welcome_strings.grdp
@@ -30,6 +30,11 @@ <message name="IDS_ONBOARDING_WELCOME_NUX_GOOGLE_APPS_DESCRIPTION" desc="Description of what this section in the onboarding workflow does."> Add bookmarks to your favorite Google Apps </message> + <if expr="_google_chrome"> + <message name="IDS_ONBOARDING_WELCOME_NUX_GOOGLE_SEARCH" desc="Label for a button that creates a bookmark to google.com, this should be the name of the brand."> + Google + </message> + </if> <message name="IDS_ONBOARDING_WELCOME_NUX_GOOGLE_GMAIL" desc="Label for a button that creates a bookmark to gmail.com, this should be the name of the brand."> Gmail </message>
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 92e3ff7b..8d12ea95 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -1509,6 +1509,9 @@ <message name="IDS_SETTINGS_PRINTING_CUPS_MANUFACTURER_MODEL_ADDITIONAL_INFORMATION" desc="Informational text displayed to the user when the the user is doing advanced manual printer setup."> <ph name="PRINTER_NAME">$1<ex>Printer</ex></ph> could not be configured automatically. Please specify advanced printer details. </message> + <message name="IDS_SETTINGS_PRINTING_CUPS_EULA_NOTICE" desc="The message shown to users if a printer has a EULA agreement attached to it."> + End User License Agreement + </message> </if> <if expr="not chromeos"> <message name="IDS_SETTINGS_PRINTING_LOCAL_PRINTERS_TITLE" desc="In Printing Settings, the title of local printers setting section on OS other than Chrome OS."> @@ -1626,18 +1629,6 @@ <message name="IDS_SETTINGS_KERBEROS_ACCOUNTS_REAUTHENTICATION_LABEL" desc="Label of the re-authentication button on Kerberos Accounts Settings page."> Sign in </message> - <message name="IDS_SETTINGS_ADD_KERBEROS_ACCOUNT" desc="In Add Kerberos Accounts dialog, the title of the dialog."> - Add Kerberos Account - </message> - <message name="IDS_SETTINGS_KERBEROS_USERNAME" desc="Title for the input that lets users specify their username for a Kerberos account."> - Username - </message> - <message name="IDS_SETTINGS_KERBEROS_PASSWORD" desc="Title for the input that lets users specify their password for a Kerberos account."> - Password - </message> - <message name="IDS_SETTINGS_KERBEROS_GENERAL_ERROR_MESSAGE" desc="Fallback error message displayed in the Add Kerberos."> - Oops! Something went wrong (error code <ph name="ERROR_CODE">$1<ex>123</ex></ph>). - </message> </if> <!-- Date/Time Page -->
diff --git a/chrome/browser/browser_process_platform_part_chromeos.cc b/chrome/browser/browser_process_platform_part_chromeos.cc index 65334bee..366a5872 100644 --- a/chrome/browser/browser_process_platform_part_chromeos.cc +++ b/chrome/browser/browser_process_platform_part_chromeos.cc
@@ -44,8 +44,6 @@ #include "services/service_manager/public/cpp/service.h" #include "services/ws/public/cpp/input_devices/input_device_controller.h" #include "services/ws/public/cpp/input_devices/input_device_controller_client.h" -#include "services/ws/public/mojom/constants.mojom.h" -#include "ui/base/ui_base_features.h" BrowserProcessPlatformPart::BrowserProcessPlatformPart() : created_profile_helper_(false), @@ -201,13 +199,10 @@ ws::InputDeviceControllerClient* BrowserProcessPlatformPart::GetInputDeviceControllerClient() { if (!input_device_controller_client_) { - const std::string service_name = !features::IsMultiProcessMash() - ? chromeos::kChromeServiceName - : ws::mojom::kServiceName; input_device_controller_client_ = std::make_unique<ws::InputDeviceControllerClient>( content::ServiceManagerConnection::GetForProcess()->GetConnector(), - service_name); + chromeos::kChromeServiceName); } return input_device_controller_client_.get(); }
diff --git a/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc b/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc index be85c3b8e..0b8f9dd 100644 --- a/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc +++ b/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc
@@ -3,7 +3,6 @@ // found in the LICENSE file. #include <memory> -#include <utility> #include <vector> #include "ash/accessibility/accessibility_focus_ring_controller.h" @@ -314,15 +313,15 @@ "<span lang='en-US'>The first paragraph</span>" "<span lang='fr-FR'>la deuxième paragraphe</span></div>"); - std::pair<std::string, std::string> result1 = + SpeechMonitorUtterance result1 = speech_monitor_.GetNextUtteranceWithLanguage(); - EXPECT_TRUE(base::MatchPattern(result1.first, "The first paragraph*")); - EXPECT_EQ("en-US", result1.second); + EXPECT_TRUE(base::MatchPattern(result1.text, "The first paragraph*")); + EXPECT_EQ("en-US", result1.lang); - std::pair<std::string, std::string> result2 = + SpeechMonitorUtterance result2 = speech_monitor_.GetNextUtteranceWithLanguage(); - EXPECT_TRUE(base::MatchPattern(result2.first, "la deuxième paragraphe*")); - EXPECT_EQ("fr-FR", result2.second); + EXPECT_TRUE(base::MatchPattern(result2.text, "la deuxième paragraphe*")); + EXPECT_EQ("fr-FR", result2.lang); } // Flaky test. https://crbug.com/950049
diff --git a/chrome/browser/chromeos/accessibility/speech_monitor.cc b/chrome/browser/chromeos/accessibility/speech_monitor.cc index 0ae533d..3ea5d4f1 100644 --- a/chrome/browser/chromeos/accessibility/speech_monitor.cc +++ b/chrome/browser/chromeos/accessibility/speech_monitor.cc
@@ -25,17 +25,16 @@ } std::string SpeechMonitor::GetNextUtterance() { - return GetNextUtteranceWithLanguage().first; + return GetNextUtteranceWithLanguage().text; } -std::pair<std::string, std::string> -SpeechMonitor::GetNextUtteranceWithLanguage() { +SpeechMonitorUtterance SpeechMonitor::GetNextUtteranceWithLanguage() { if (utterance_queue_.empty()) { loop_runner_ = new content::MessageLoopRunner(); loop_runner_->Run(); loop_runner_ = NULL; } - std::pair<std::string, std::string> result = utterance_queue_.front(); + SpeechMonitorUtterance result = utterance_queue_.front(); utterance_queue_.pop_front(); return result; } @@ -63,9 +62,9 @@ loop_runner_->Run(); loop_runner_ = NULL; } - std::pair<std::string, std::string> result = utterance_queue_.front(); + SpeechMonitorUtterance result = utterance_queue_.front(); utterance_queue_.pop_front(); - if (result.first == message) + if (result.text == message) return true; } return false; @@ -117,8 +116,7 @@ return; VLOG(0) << "Speaking " << utterance->GetText(); - utterance_queue_.push_back( - std::make_pair(utterance->GetText(), utterance->GetLang())); + utterance_queue_.emplace_back(utterance->GetText(), utterance->GetLang()); if (loop_runner_.get()) loop_runner_->Quit(); }
diff --git a/chrome/browser/chromeos/accessibility/speech_monitor.h b/chrome/browser/chromeos/accessibility/speech_monitor.h index 9c28ec7..4ad7abe 100644 --- a/chrome/browser/chromeos/accessibility/speech_monitor.h +++ b/chrome/browser/chromeos/accessibility/speech_monitor.h
@@ -5,8 +5,6 @@ #ifndef CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_SPEECH_MONITOR_H_ #define CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_SPEECH_MONITOR_H_ -#include <utility> - #include "base/containers/circular_deque.h" #include "base/macros.h" #include "base/memory/ref_counted.h" @@ -17,6 +15,13 @@ namespace chromeos { +struct SpeechMonitorUtterance { + SpeechMonitorUtterance(std::string text_, std::string lang_) + : text(text_), lang(lang_) {} + std::string text; + std::string lang; +}; + // For testing purpose installs itself as the platform speech synthesis engine, // allowing it to intercept all speech calls, and then provides a method to // block until the next utterance is spoken. @@ -28,7 +33,7 @@ // Blocks until the next utterance is spoken, and returns its text. std::string GetNextUtterance(); // Blocks until the next utterance is spoken, and returns its text. - std::pair<std::string, std::string> GetNextUtteranceWithLanguage(); + SpeechMonitorUtterance GetNextUtteranceWithLanguage(); // Wait for next utterance and return true if next utterance is ChromeVox // enabled message. @@ -65,7 +70,7 @@ scoped_refptr<content::MessageLoopRunner> loop_runner_; // Our list of utterances and specified language. - base::circular_deque<std::pair<std::string, std::string>> utterance_queue_; + base::circular_deque<SpeechMonitorUtterance> utterance_queue_; bool did_stop_ = false; std::string error_;
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_bridge.cc b/chrome/browser/chromeos/arc/fileapi/arc_file_system_bridge.cc index bc7e681..cc73ebbe 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_bridge.cc +++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_bridge.cc
@@ -76,11 +76,15 @@ // Converts the given URL to a FileSystemURL. storage::FileSystemURL GetFileSystemURL( scoped_refptr<storage::FileSystemContext> context, - const GURL& url) { + const GURL& url, + storage::IsolatedContext::ScopedFSHandle* file_system) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - return file_manager::util::CreateIsolatedURLFromVirtualPath( - *context, /* empty origin */ GURL(), - chromeos::ExternalFileURLToVirtualPath(url)); + storage::FileSystemURL result; + std::tie(result, *file_system) = + file_manager::util::CreateIsolatedURLFromVirtualPath( + *context, /* empty origin */ GURL(), + chromeos::ExternalFileURLToVirtualPath(url)); + return result; } // Retrieves the file size on the IO thread, and runs the callback on the UI @@ -244,11 +248,18 @@ } scoped_refptr<storage::FileSystemContext> context = GetFileSystemContext(profile_, url_decoded); + storage::IsolatedContext::ScopedFSHandle isolated_file_system; base::PostTaskWithTraits( FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&GetFileSizeOnIOThread, context, - GetFileSystemURL(context, url_decoded), - std::move(callback))); + base::BindOnce( + &GetFileSizeOnIOThread, context, + GetFileSystemURL(context, url_decoded, &isolated_file_system), + std::move(callback))); + // TODO(https://crbug.com/963027): This is currently leaking the isolated + // file system, the file system should somehow be revoked when the url + // returned by GetFileSystemURL is no longer needed. + storage::IsolatedContext::GetInstance()->AddReference( + isolated_file_system.id()); } void ArcFileSystemBridge::GetFileType(const std::string& url, @@ -262,8 +273,9 @@ } scoped_refptr<storage::FileSystemContext> context = GetFileSystemContext(profile_, url_decoded); + storage::IsolatedContext::ScopedFSHandle file_system; storage::FileSystemURL file_system_url = - GetFileSystemURL(context, url_decoded); + GetFileSystemURL(context, url_decoded, &file_system); extensions::app_file_handler_util::GetMimeTypeForLocalPath( profile_, file_system_url.path(), base::Bind( @@ -405,11 +417,16 @@ const GURL& url = it_url->second; scoped_refptr<storage::FileSystemContext> context = GetFileSystemContext(profile_, url); + storage::IsolatedContext::ScopedFSHandle file_system; *it_forwarder = FileStreamForwarderPtr(new FileStreamForwarder( - context, GetFileSystemURL(context, url), offset, size, + context, GetFileSystemURL(context, url, &file_system), offset, size, std::move(pipe_write_end), base::BindOnce(&ArcFileSystemBridge::OnReadRequestCompleted, weak_ptr_factory_.GetWeakPtr(), id, it_forwarder))); + // TODO(https://crbug.com/963027): This is currently leaking the isolated + // file system, the file system should somehow be revoked when the url + // returned by GetFileSystemURL is no longer needed. + storage::IsolatedContext::GetInstance()->AddReference(file_system.id()); return true; }
diff --git a/chrome/browser/chromeos/arc/video/gpu_arc_video_service_host.cc b/chrome/browser/chromeos/arc/video/gpu_arc_video_service_host.cc index eef36d9..f796d9b 100644 --- a/chrome/browser/chromeos/arc/video/gpu_arc_video_service_host.cc +++ b/chrome/browser/chromeos/arc/video/gpu_arc_video_service_host.cc
@@ -30,8 +30,6 @@ #include "mojo/public/cpp/system/platform_handle.h" #include "services/service_manager/public/cpp/connector.h" #include "services/ws/public/mojom/arc_gpu.mojom.h" -#include "services/ws/public/mojom/constants.mojom.h" -#include "ui/base/ui_base_features.h" namespace arc { @@ -58,7 +56,7 @@ class VideoAcceleratorFactoryService : public mojom::VideoAcceleratorFactory { public: - VideoAcceleratorFactoryService() { DCHECK(!features::IsMultiProcessMash()); } + VideoAcceleratorFactoryService() = default; ~VideoAcceleratorFactoryService() override = default; @@ -93,54 +91,6 @@ DISALLOW_COPY_AND_ASSIGN(VideoAcceleratorFactoryService); }; -class VideoAcceleratorFactoryServiceViz - : public mojom::VideoAcceleratorFactory { - public: - VideoAcceleratorFactoryServiceViz() { - DCHECK(features::IsMultiProcessMash()); - DETACH_FROM_THREAD(thread_checker_); - auto* connector = - content::ServiceManagerConnection::GetForProcess()->GetConnector(); - connector->BindInterface(ws::mojom::kServiceName, &arc_gpu_); - } - - ~VideoAcceleratorFactoryServiceViz() override { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - } - - void CreateDecodeAccelerator( - mojom::VideoDecodeAcceleratorRequest request) override { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - arc_gpu_->CreateVideoDecodeAccelerator(std::move(request)); - } - - void CreateEncodeAccelerator( - mojom::VideoEncodeAcceleratorRequest request) override { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - arc_gpu_->CreateVideoEncodeAccelerator(std::move(request)); - } - - void CreateProtectedBufferAllocator( - mojom::VideoProtectedBufferAllocatorRequest request) override { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - arc_gpu_->CreateVideoProtectedBufferAllocator(std::move(request)); - } - - private: - THREAD_CHECKER(thread_checker_); - - ws::mojom::ArcGpuPtr arc_gpu_; - - DISALLOW_COPY_AND_ASSIGN(VideoAcceleratorFactoryServiceViz); -}; - -std::unique_ptr<mojom::VideoAcceleratorFactory> -CreateVideoAcceleratorFactory() { - if (features::IsMultiProcessMash()) - return std::make_unique<VideoAcceleratorFactoryServiceViz>(); - return std::make_unique<VideoAcceleratorFactoryService>(); -} - } // namespace // static @@ -152,7 +102,8 @@ GpuArcVideoServiceHost::GpuArcVideoServiceHost(content::BrowserContext* context, ArcBridgeService* bridge_service) : arc_bridge_service_(bridge_service), - video_accelerator_factory_(CreateVideoAcceleratorFactory()) { + video_accelerator_factory_( + std::make_unique<VideoAcceleratorFactoryService>()) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); arc_bridge_service_->video()->SetHost(this); }
diff --git a/chrome/browser/chromeos/drive/file_system_util_unittest.cc b/chrome/browser/chromeos/drive/file_system_util_unittest.cc index 6a49941..8291470 100644 --- a/chrome/browser/chromeos/drive/file_system_util_unittest.cc +++ b/chrome/browser/chromeos/drive/file_system_util_unittest.cc
@@ -166,7 +166,7 @@ // Type:"isolated" + virtual_path:"isolated_id/name" mapped on a Drive path. std::string isolated_name; - std::string isolated_id = + storage::IsolatedContext::ScopedFSHandle isolated_fs = storage::IsolatedContext::GetInstance()->RegisterFileSystemForPath( storage::kFileSystemTypeNativeForPlatformApp, std::string(), GetDriveMountPointPath(&profile).AppendASCII("bar/buz"), @@ -174,7 +174,7 @@ EXPECT_EQ(base::FilePath::FromUTF8Unsafe("drive/bar/buz"), ExtractDrivePathFromFileSystemUrl(context->CrackURL( GURL("filesystem:chrome-extension://dummy-id/isolated/" + - isolated_id + "/" + isolated_name)))); + isolated_fs.id() + "/" + isolated_name)))); } TEST_F(ProfileRelatedFileSystemUtilTest, GetCacheRootPath) {
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc index d4b0d14..97b8797e 100644 --- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc +++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -79,7 +79,6 @@ #include "mojo/public/cpp/bindings/associated_binding.h" #include "net/base/filename_util.h" #include "services/service_manager/public/cpp/connector.h" -#include "services/ws/public/mojom/constants.mojom.h" #include "ui/base/ime/ime_bridge.h" #include "ui/base/ui_base_features.h" #include "ui/display/display.h" @@ -1542,63 +1541,6 @@ } /////////////////////////////////////////////////////////////////////////////// -// AutotestPrivateEnsureWindowServiceClientHasDrawnWindowFunction -/////////////////////////////////////////////////////////////////////////////// - -AutotestPrivateEnsureWindowServiceClientHasDrawnWindowFunction:: - AutotestPrivateEnsureWindowServiceClientHasDrawnWindowFunction() = default; -AutotestPrivateEnsureWindowServiceClientHasDrawnWindowFunction:: - ~AutotestPrivateEnsureWindowServiceClientHasDrawnWindowFunction() = default; - -ExtensionFunction::ResponseAction -AutotestPrivateEnsureWindowServiceClientHasDrawnWindowFunction::Run() { - auto params = api::autotest_private::EnsureWindowServiceClientHasDrawnWindow:: - Params::Create(*args_); - EXTENSION_FUNCTION_VALIDATE(params); - - service_manager::Connector* connector = - content::ServiceManagerConnection::GetForProcess()->GetConnector(); - connector->BindInterface( - service_manager::ServiceFilter::ByName(ws::mojom::kServiceName), - mojo::MakeRequest(&window_server_test_ptr_)); - window_server_test_ptr_->EnsureClientHasDrawnWindow( - params->client_name, - base::BindOnce( - &AutotestPrivateEnsureWindowServiceClientHasDrawnWindowFunction:: - OnEnsureClientHasDrawnWindowCallback, - this)); - - timeout_timer_.Start( - FROM_HERE, base::TimeDelta::FromMilliseconds(params->timeout_ms), - base::BindOnce( - &AutotestPrivateEnsureWindowServiceClientHasDrawnWindowFunction:: - OnTimeout, - this)); - - return RespondLater(); -} - -void AutotestPrivateEnsureWindowServiceClientHasDrawnWindowFunction:: - OnEnsureClientHasDrawnWindowCallback(bool success) { - if (did_respond()) { - LOG(ERROR) << "EnsureClientHasDrawnWindow returned after timeout: " - << success; - return; - } - - Respond(OneArgument(std::make_unique<base::Value>(success))); - timeout_timer_.AbandonAndStop(); -} - -void AutotestPrivateEnsureWindowServiceClientHasDrawnWindowFunction:: - OnTimeout() { - if (did_respond()) - return; - - Respond(Error("EnsureWindowServiceClientHasDrawnWindowFunction timeout.")); -} - -/////////////////////////////////////////////////////////////////////////////// // AutotestPrivateGetPrimaryDisplayScaleFactorFunction ///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h index f95a886..49badeb 100644 --- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h +++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
@@ -22,7 +22,6 @@ #include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h" #include "chromeos/services/machine_learning/public/mojom/model.mojom.h" #include "extensions/browser/browser_context_keyed_api_factory.h" -#include "services/ws/public/mojom/window_server_test.mojom.h" #include "ui/message_center/public/cpp/notification_types.h" #include "ui/snapshot/screenshot_grabber.h" @@ -567,26 +566,6 @@ ResponseAction Run() override; }; -// Ensure a Window Service client has drawn windows with a timeout. -class AutotestPrivateEnsureWindowServiceClientHasDrawnWindowFunction - : public UIThreadExtensionFunction { - public: - AutotestPrivateEnsureWindowServiceClientHasDrawnWindowFunction(); - DECLARE_EXTENSION_FUNCTION( - "autotestPrivate.ensureWindowServiceClientHasDrawnWindow", - AUTOTESTPRIVATE_ENSUREWINDOWSERVICECLIENTHASDRAWNWINDOW) - - private: - ~AutotestPrivateEnsureWindowServiceClientHasDrawnWindowFunction() override; - ResponseAction Run() override; - - void OnEnsureClientHasDrawnWindowCallback(bool success); - void OnTimeout(); - - ws::mojom::WindowServerTestPtr window_server_test_ptr_; - base::OneShotTimer timeout_timer_; -}; - // The profile-keyed service that manages the autotestPrivate extension API. class AutotestPrivateAPI : public BrowserContextKeyedAPI { public:
diff --git a/chrome/browser/chromeos/extensions/input_method_api.cc b/chrome/browser/chromeos/extensions/input_method_api.cc index a26aa86..866c2598 100644 --- a/chrome/browser/chromeos/extensions/input_method_api.cc +++ b/chrome/browser/chromeos/extensions/input_method_api.cc
@@ -42,6 +42,7 @@ #include "ui/base/ime/chromeos/input_method_util.h" #include "ui/base/ime/ime_bridge.h" +namespace input_method_private = extensions::api::input_method_private; namespace AddWordToDictionary = extensions::api::input_method_private::AddWordToDictionary; namespace SetCurrentInputMethod = @@ -64,9 +65,13 @@ extensions::api::input_method_private::GetSurroundingText; namespace GetSetting = extensions::api::input_method_private::GetSetting; namespace SetSetting = extensions::api::input_method_private::SetSetting; +namespace SetCompositionRange = + extensions::api::input_method_private::SetCompositionRange; namespace OnSettingsChanged = extensions::api::input_method_private::OnSettingsChanged; +using input_method::InputMethodEngineBase; + namespace { // Prefix, which is used by XKB. @@ -386,6 +391,51 @@ #endif } +ExtensionFunction::ResponseAction +InputMethodPrivateSetCompositionRangeFunction::Run() { + InputImeEventRouter* event_router = + GetInputImeEventRouter(Profile::FromBrowserContext(browser_context())); + InputMethodEngineBase* engine = + event_router ? event_router->GetActiveEngine(extension_id()) : nullptr; + if (engine) { + const auto parent_params = SetCompositionRange::Params::Create(*args_); + const auto& params = parent_params->parameters; + std::vector<InputMethodEngineBase::SegmentInfo> segments; + if (params.segments) { + for (const auto& segments_arg : *params.segments) { + InputMethodEngineBase::SegmentInfo segment_info; + segment_info.start = segments_arg.start; + segment_info.end = segments_arg.end; + switch (segments_arg.style) { + case input_method_private::UNDERLINE_STYLE_UNDERLINE: + segment_info.style = InputMethodEngineBase::SEGMENT_STYLE_UNDERLINE; + break; + case input_method_private::UNDERLINE_STYLE_NONE: + EXTENSION_FUNCTION_VALIDATE(false); + break; + } + segments.push_back(segment_info); + } + } else { + // Default to a single segment that spans the entire range. + InputMethodEngineBase::SegmentInfo segment_info; + segment_info.start = 0; + segment_info.end = params.selection_before + params.selection_after; + segment_info.style = InputMethodEngineBase::SEGMENT_STYLE_UNDERLINE; + segments.push_back(segment_info); + } + std::string error; + if (!engine->SetCompositionRange(params.context_id, params.selection_before, + params.selection_after, segments, + &error)) { + auto results = std::make_unique<base::ListValue>(); + results->Append(std::make_unique<base::Value>(false)); + return RespondNow(ErrorWithArguments(std::move(results), error)); + } + } + return RespondNow(OneArgument(std::make_unique<base::Value>(true))); +} + InputMethodAPI::InputMethodAPI(content::BrowserContext* context) : context_(context) { EventRouter::Get(context_)->RegisterObserver(this, OnChanged::kEventName);
diff --git a/chrome/browser/chromeos/extensions/input_method_api.h b/chrome/browser/chromeos/extensions/input_method_api.h index b720e08..ac44931 100644 --- a/chrome/browser/chromeos/extensions/input_method_api.h +++ b/chrome/browser/chromeos/extensions/input_method_api.h
@@ -240,6 +240,19 @@ DISALLOW_COPY_AND_ASSIGN(InputMethodPrivateSetSettingFunction); }; +class InputMethodPrivateSetCompositionRangeFunction + : public UIThreadExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("inputMethodPrivate.setCompositionRange", + INPUTMETHODPRIVATE_SETCOMPOSITIONRANGE) + + protected: + ~InputMethodPrivateSetCompositionRangeFunction() override {} + + // UIThreadExtensionFunction: + ResponseAction Run() override; +}; + class InputMethodAPI : public BrowserContextKeyedAPI, public extensions::EventRouter::Observer { public:
diff --git a/chrome/browser/chromeos/extensions/input_method_apitest_chromeos.cc b/chrome/browser/chromeos/extensions/input_method_apitest_chromeos.cc index 9178c633..22251a3 100644 --- a/chrome/browser/chromeos/extensions/input_method_apitest_chromeos.cc +++ b/chrome/browser/chromeos/extensions/input_method_apitest_chromeos.cc
@@ -12,6 +12,7 @@ #include "chrome/browser/chromeos/extensions/input_method_event_router.h" #include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" +#include "chrome/test/base/ui_test_utils.h" #include "chromeos/constants/chromeos_switches.h" #include "components/prefs/pref_service.h" #include "content/public/browser/notification_observer.h" @@ -103,6 +104,21 @@ ASSERT_TRUE(RunExtensionTest("input_method/basic")) << message_; } +IN_PROC_BROWSER_TEST_F(ExtensionInputMethodApiTest, Typing) { + // Enable the test IME from the test extension. + std::vector<std::string> extension_ime_ids = { + "_ext_ime_ilanclmaeigfpnmdlgelmhkpkegdioiptest"}; + InputMethodManager::Get()->GetActiveIMEState()->SetEnabledExtensionImes( + &extension_ime_ids); + + GURL test_url = ui_test_utils::GetTestUrl( + base::FilePath("extensions/api_test/input_method/typing/"), + base::FilePath("test_page.html")); + ui_test_utils::NavigateToURL(browser(), test_url); + + ASSERT_TRUE(RunExtensionTest("input_method/typing")) << message_; +} + IN_PROC_BROWSER_TEST_F(ExtensionInputMethodApiTest, ImeMenuActivation) { // Listener for IME menu initial state ready. ExtensionTestMessageListener config_listener("config_ready", false);
diff --git a/chrome/browser/chromeos/file_manager/fileapi_util.cc b/chrome/browser/chromeos/file_manager/fileapi_util.cc index fad604fe..b96934d 100644 --- a/chrome/browser/chromeos/file_manager/fileapi_util.cc +++ b/chrome/browser/chromeos/file_manager/fileapi_util.cc
@@ -304,13 +304,21 @@ return; } - const GURL url = CreateIsolatedURLFromVirtualPath( - *context_, origin, virtual_path).ToGURL(); + storage::FileSystemURL file_system_url; + storage::IsolatedContext::ScopedFSHandle file_system; + std::tie(file_system_url, file_system) = + CreateIsolatedURLFromVirtualPath(*context_, origin, virtual_path); + const GURL url = file_system_url.ToGURL(); if (!url.is_valid()) { NotifyError(std::move(lifetime)); return; } + // Increase ref count of file system to keep it alive after |file_system| + // goes out of scope. Our destructor will eventually revoke the file + // system. + storage::IsolatedContext::GetInstance()->AddReference(file_system.id()); + auto fs_info = FileSystemFileInfo::New(); fs_info->url = url; chooser_info_list_.push_back( @@ -627,27 +635,23 @@ google_apis::CreateRelayCallback(std::move(callback)))); } -storage::FileSystemURL CreateIsolatedURLFromVirtualPath( - const storage::FileSystemContext& context, - const GURL& origin, - const base::FilePath& virtual_path) { +std::pair<storage::FileSystemURL, storage::IsolatedContext::ScopedFSHandle> +CreateIsolatedURLFromVirtualPath(const storage::FileSystemContext& context, + const GURL& origin, + const base::FilePath& virtual_path) { const storage::FileSystemURL original_url = context.CreateCrackedFileSystemURL( origin, storage::kFileSystemTypeExternal, virtual_path); std::string register_name; - const std::string isolated_file_system_id = + storage::IsolatedContext::ScopedFSHandle file_system = storage::IsolatedContext::GetInstance()->RegisterFileSystemForPath( - original_url.type(), - original_url.filesystem_id(), - original_url.path(), - ®ister_name); - const storage::FileSystemURL isolated_url = - context.CreateCrackedFileSystemURL( - origin, - storage::kFileSystemTypeIsolated, - base::FilePath(isolated_file_system_id).Append(register_name)); - return isolated_url; + original_url.type(), original_url.filesystem_id(), + original_url.path(), ®ister_name); + storage::FileSystemURL isolated_url = context.CreateCrackedFileSystemURL( + origin, storage::kFileSystemTypeIsolated, + base::FilePath(file_system.id()).Append(register_name)); + return {isolated_url, file_system}; } } // namespace util
diff --git a/chrome/browser/chromeos/file_manager/fileapi_util.h b/chrome/browser/chromeos/file_manager/fileapi_util.h index 1bc9df2..ff297bed 100644 --- a/chrome/browser/chromeos/file_manager/fileapi_util.h +++ b/chrome/browser/chromeos/file_manager/fileapi_util.h
@@ -15,6 +15,7 @@ #include "base/files/file.h" #include "base/files/file_path.h" #include "storage/browser/fileapi/file_system_operation_runner.h" +#include "storage/browser/fileapi/isolated_context.h" #include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h" #include "url/gurl.h" @@ -172,10 +173,10 @@ // Obtains isolated file system URL from |virtual_path| pointing a file in the // external file system. -storage::FileSystemURL CreateIsolatedURLFromVirtualPath( - const storage::FileSystemContext& context, - const GURL& origin, - const base::FilePath& virtual_path); +std::pair<storage::FileSystemURL, storage::IsolatedContext::ScopedFSHandle> +CreateIsolatedURLFromVirtualPath(const storage::FileSystemContext& context, + const GURL& origin, + const base::FilePath& virtual_path); } // namespace util } // namespace file_manager
diff --git a/chrome/browser/chromeos/file_system_provider/mount_path_util_unittest.cc b/chrome/browser/chromeos/file_system_provider/mount_path_util_unittest.cc index bf4b57e44..0ca812335 100644 --- a/chrome/browser/chromeos/file_system_provider/mount_path_util_unittest.cc +++ b/chrome/browser/chromeos/file_system_provider/mount_path_util_unittest.cc
@@ -211,15 +211,13 @@ // Create an isolated URL for the original one. storage::IsolatedContext* const isolated_context = storage::IsolatedContext::GetInstance(); - const std::string isolated_file_system_id = + const storage::IsolatedContext::ScopedFSHandle isolated_file_system = isolated_context->RegisterFileSystemForPath( - storage::kFileSystemTypeProvided, - url.filesystem_id(), - url.path(), + storage::kFileSystemTypeProvided, url.filesystem_id(), url.path(), NULL); const base::FilePath isolated_virtual_path = - isolated_context->CreateVirtualRootPath(isolated_file_system_id) + isolated_context->CreateVirtualRootPath(isolated_file_system.id()) .Append(kFilePath.BaseName().value()); const storage::FileSystemURL isolated_url =
diff --git a/chrome/browser/chromeos/fileapi/external_file_resolver.cc b/chrome/browser/chromeos/fileapi/external_file_resolver.cc index b91c3c49..166638c 100644 --- a/chrome/browser/chromeos/fileapi/external_file_resolver.cc +++ b/chrome/browser/chromeos/fileapi/external_file_resolver.cc
@@ -39,7 +39,7 @@ using HelperCallback = base::OnceCallback<void( net::Error, const scoped_refptr<storage::FileSystemContext>& file_system_context, - std::unique_ptr<IsolatedFileSystemScope> isolated_file_system_scope, + storage::IsolatedContext::ScopedFSHandle isolated_file_system_scope, const storage::FileSystemURL& file_system_url, const std::string& mime_type)>; @@ -73,8 +73,9 @@ const base::FilePath virtual_path = ExternalFileURLToVirtualPath(url); // Obtain the file system URL. - file_system_url_ = file_manager::util::CreateIsolatedURLFromVirtualPath( - *context, /* empty origin */ GURL(), virtual_path); + std::tie(file_system_url_, isolated_file_system_scope_) = + file_manager::util::CreateIsolatedURLFromVirtualPath( + *context, /* empty origin */ GURL(), virtual_path); // Check if the obtained path providing external file URL or not. if (!file_system_url_.is_valid()) { @@ -82,9 +83,6 @@ return; } - isolated_file_system_scope_.reset( - new IsolatedFileSystemScope(file_system_url_.filesystem_id())); - if (!IsExternalFileURLType(file_system_url_.type())) { ReplyResult(net::ERR_FAILED); return; @@ -114,13 +112,13 @@ base::PostTaskWithTraits( FROM_HERE, {content::BrowserThread::IO}, base::BindOnce(std::move(callback_), error, file_system_context_, - base::Passed(&isolated_file_system_scope_), - file_system_url_, mime_type_)); + std::move(isolated_file_system_scope_), file_system_url_, + mime_type_)); } HelperCallback callback_; scoped_refptr<storage::FileSystemContext> file_system_context_; - std::unique_ptr<IsolatedFileSystemScope> isolated_file_system_scope_; + storage::IsolatedContext::ScopedFSHandle isolated_file_system_scope_; storage::FileSystemURL file_system_url_; std::string mime_type_; @@ -129,14 +127,6 @@ } // namespace -IsolatedFileSystemScope::IsolatedFileSystemScope( - const std::string& file_system_id) - : file_system_id_(file_system_id) {} - -IsolatedFileSystemScope::~IsolatedFileSystemScope() { - storage::IsolatedContext::GetInstance()->RevokeFileSystem(file_system_id_); -} - ExternalFileResolver::ExternalFileResolver(void* profile_id) : profile_id_(profile_id), range_parse_result_(net::OK), @@ -202,7 +192,7 @@ void ExternalFileResolver::OnHelperResultObtained( net::Error error, const scoped_refptr<storage::FileSystemContext>& file_system_context, - std::unique_ptr<IsolatedFileSystemScope> isolated_file_system_scope, + storage::IsolatedContext::ScopedFSHandle isolated_file_system_scope, const storage::FileSystemURL& file_system_url, const std::string& mime_type) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
diff --git a/chrome/browser/chromeos/fileapi/external_file_resolver.h b/chrome/browser/chromeos/fileapi/external_file_resolver.h index 2901c0e6..3305758 100644 --- a/chrome/browser/chromeos/fileapi/external_file_resolver.h +++ b/chrome/browser/chromeos/fileapi/external_file_resolver.h
@@ -15,6 +15,7 @@ #include "net/base/net_errors.h" #include "net/http/http_byte_range.h" #include "storage/browser/fileapi/file_system_url.h" +#include "storage/browser/fileapi/isolated_context.h" #include "url/gurl.h" namespace net { @@ -28,17 +29,6 @@ namespace chromeos { -// Scope of isolated file system. -class IsolatedFileSystemScope { - public: - explicit IsolatedFileSystemScope(const std::string& file_system_id); - ~IsolatedFileSystemScope(); - - private: - std::string file_system_id_; - DISALLOW_COPY_AND_ASSIGN(IsolatedFileSystemScope); -}; - // Resolves an externalfile URL to a redirect or a FileStreamReader. class ExternalFileResolver { public: @@ -47,7 +37,7 @@ const GURL& redirect_url)>; using StreamCallback = base::OnceCallback<void( const std::string& mime_type, - std::unique_ptr<IsolatedFileSystemScope> isolated_file_system_scope, + storage::IsolatedContext::ScopedFSHandle isolated_file_system_scope, std::unique_ptr<storage::FileStreamReader> stream_reader, int64_t size)>; @@ -70,7 +60,7 @@ void OnHelperResultObtained( net::Error error, const scoped_refptr<storage::FileSystemContext>& file_system_context, - std::unique_ptr<IsolatedFileSystemScope> isolated_file_system_scope, + storage::IsolatedContext::ScopedFSHandle isolated_file_system_scope, const storage::FileSystemURL& file_system_url, const std::string& mime_type); @@ -88,7 +78,7 @@ StreamCallback stream_callback_; scoped_refptr<storage::FileSystemContext> file_system_context_; - std::unique_ptr<IsolatedFileSystemScope> isolated_file_system_scope_; + storage::IsolatedContext::ScopedFSHandle isolated_file_system_scope_; storage::FileSystemURL file_system_url_; std::string mime_type_; base::WeakPtrFactory<ExternalFileResolver> weak_ptr_factory_;
diff --git a/chrome/browser/chromeos/fileapi/external_file_url_loader_factory.cc b/chrome/browser/chromeos/fileapi/external_file_url_loader_factory.cc index 5ecaf341..f03c16c 100644 --- a/chrome/browser/chromeos/fileapi/external_file_url_loader_factory.cc +++ b/chrome/browser/chromeos/fileapi/external_file_url_loader_factory.cc
@@ -264,7 +264,7 @@ void OnStreamObtained( const std::string& mime_type, - std::unique_ptr<IsolatedFileSystemScope> isolated_file_system_scope, + storage::IsolatedContext::ScopedFSHandle isolated_file_system_scope, std::unique_ptr<storage::FileStreamReader> stream_reader, int64_t size) { head_.mime_type = mime_type; @@ -326,7 +326,7 @@ std::unique_ptr<ExternalFileResolver> resolver_; network::ResourceResponseHead head_; - std::unique_ptr<IsolatedFileSystemScope> isolated_file_system_scope_; + storage::IsolatedContext::ScopedFSHandle isolated_file_system_scope_; std::unique_ptr<FileSystemReaderDataPipeProducer> data_producer_; base::WeakPtrFactory<ExternalFileURLLoader> weak_ptr_factory_;
diff --git a/chrome/browser/chromeos/fileapi/external_file_url_request_job.cc b/chrome/browser/chromeos/fileapi/external_file_url_request_job.cc index 9eff600..d38a438 100644 --- a/chrome/browser/chromeos/fileapi/external_file_url_request_job.cc +++ b/chrome/browser/chromeos/fileapi/external_file_url_request_job.cc
@@ -62,7 +62,7 @@ void ExternalFileURLRequestJob::OnStreamObtained( const std::string& mime_type, - std::unique_ptr<IsolatedFileSystemScope> isolated_file_system_scope, + storage::IsolatedContext::ScopedFSHandle isolated_file_system_scope, std::unique_ptr<storage::FileStreamReader> stream_reader, int64_t size) { mime_type_ = mime_type; @@ -82,7 +82,7 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); resolver_.reset(); stream_reader_.reset(); - isolated_file_system_scope_.reset(); + isolated_file_system_scope_ = {}; net::URLRequestJob::Kill(); weak_ptr_factory_.InvalidateWeakPtrs(); }
diff --git a/chrome/browser/chromeos/fileapi/external_file_url_request_job.h b/chrome/browser/chromeos/fileapi/external_file_url_request_job.h index e4d7dab0e..670e317 100644 --- a/chrome/browser/chromeos/fileapi/external_file_url_request_job.h +++ b/chrome/browser/chromeos/fileapi/external_file_url_request_job.h
@@ -63,7 +63,7 @@ void OnStreamObtained( const std::string& mime_type, - std::unique_ptr<IsolatedFileSystemScope> isolated_file_system_scope, + storage::IsolatedContext::ScopedFSHandle isolated_file_system_scope, std::unique_ptr<storage::FileStreamReader> stream_reader, int64_t size); @@ -75,7 +75,7 @@ std::unique_ptr<ExternalFileResolver> resolver_; std::string mime_type_; - std::unique_ptr<IsolatedFileSystemScope> isolated_file_system_scope_; + storage::IsolatedContext::ScopedFSHandle isolated_file_system_scope_; std::unique_ptr<storage::FileStreamReader> stream_reader_; int64_t remaining_bytes_; GURL redirect_url_;
diff --git a/chrome/browser/chromeos/input_method/input_method_engine.cc b/chrome/browser/chromeos/input_method/input_method_engine.cc index cc843142..cca2bc70 100644 --- a/chrome/browser/chromeos/input_method/input_method_engine.cc +++ b/chrome/browser/chromeos/input_method/input_method_engine.cc
@@ -411,6 +411,22 @@ } } +bool InputMethodEngine::SetCompositionRange( + uint32_t before, + uint32_t after, + const std::vector<ui::ImeTextSpan>& text_spans) { + if (mojo_helper_->IsConnected()) { + // TODO(https://crbug.com/952757): Implement this in Mojo. + return false; + } else { + ui::IMEInputContextHandlerInterface* input_context = + ui::IMEBridge::Get()->GetInputContextHandler(); + if (!input_context) + return false; + return input_context->SetCompositionRange(before, after, text_spans); + } +} + void InputMethodEngine::CommitTextToInputContext(int context_id, const std::string& text) { bool committed = false;
diff --git a/chrome/browser/chromeos/input_method/input_method_engine.h b/chrome/browser/chromeos/input_method/input_method_engine.h index 5a8d0e2..ea00479 100644 --- a/chrome/browser/chromeos/input_method/input_method_engine.h +++ b/chrome/browser/chromeos/input_method/input_method_engine.h
@@ -145,6 +145,10 @@ void UpdateComposition(const ui::CompositionText& composition_text, uint32_t cursor_pos, bool is_visible) override; + bool SetCompositionRange( + uint32_t before, + uint32_t after, + const std::vector<ui::ImeTextSpan>& text_spans) override; void CommitTextToInputContext(int context_id, const std::string& text) override; void DeleteSurroundingTextToInputContext(int offset,
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_local_policy_server_browsertest.cc b/chrome/browser/chromeos/login/enrollment/enrollment_local_policy_server_browsertest.cc index 6ee4121..9c85611e 100644 --- a/chrome/browser/chromeos/login/enrollment/enrollment_local_policy_server_browsertest.cc +++ b/chrome/browser/chromeos/login/enrollment/enrollment_local_policy_server_browsertest.cc
@@ -457,8 +457,15 @@ OobeScreenWaiter(GaiaView::kScreenId).Wait(); } +// https://crbug.com/965367 +#if defined(OS_CHROMEOS) +#define MAYBE_ReenrollmentNone DISABLED_ReenrollmentNone +#else +#define MAYBE_ReenrollmentNone ReenrollmentNone +#endif // State keys are present but restore mode is not requested. -IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer, ReenrollmentNone) { +IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer, + MAYBE_ReenrollmentNone) { EXPECT_TRUE(policy_server_.SetDeviceStateRetrievalResponse( state_keys_broker(), enterprise_management::DeviceStateRetrievalResponse::RESTORE_MODE_NONE,
diff --git a/chrome/browser/chromeos/printing/automatic_usb_printer_configurer.cc b/chrome/browser/chromeos/printing/automatic_usb_printer_configurer.cc index 637f826..f0e6526 100644 --- a/chrome/browser/chromeos/printing/automatic_usb_printer_configurer.cc +++ b/chrome/browser/chromeos/printing/automatic_usb_printer_configurer.cc
@@ -13,10 +13,10 @@ namespace chromeos { namespace { -bool IsInAutomaticList(const std::string& printer_id, - const std::vector<Printer>& automatic_printers) { - for (const auto& automatic_printer : automatic_printers) { - if (automatic_printer.id() == printer_id) { +bool IsPrinterIdInList(const std::string& printer_id, + const std::vector<Printer>& printer_list) { + for (const auto& printer : printer_list) { + if (printer.id() == printer_id) { return true; } } @@ -47,16 +47,33 @@ return; } - if (printer_class != PrinterClass::kAutomatic) { + if (printer_class == PrinterClass::kAutomatic) { + // Remove any notifications for printers that are no longer in the automatic + // class and setup any USB printers we haven't seen yet. + PruneRemovedAutomaticPrinters(printers); + for (const Printer& printer : printers) { + if (!configured_printers_.contains(printer.id()) && + printer.IsUsbProtocol()) { + SetupPrinter(printer); + } + } return; } - PruneRemovedPrinters(printers); - - for (const Printer& printer : printers) { - if (!printers_.contains(printer.id()) && printer.IsUsbProtocol()) { - SetupPrinter(printer); + if (printer_class == PrinterClass::kDiscovered) { + // Remove any notifications for printers that are no longer in the + // discovered class and show a configuration notification for printers we + // haven't seen yet + PruneRemovedDiscoveredPrinters(printers); + for (const Printer& printer : printers) { + if (!unconfigured_printers_.contains(printer.id()) && + printer.IsUsbProtocol()) { + notification_controller_->ShowConfigurationNotification(printer); + DCHECK(!configured_printers_.contains(printer.id())); + unconfigured_printers_.insert(printer.id()); + } } + return; } } @@ -89,15 +106,29 @@ VLOG(1) << "Auto USB Printer setup successful for " << printer.id(); notification_controller_->ShowEphemeralNotification(printer); - printers_.insert(printer.id()); + DCHECK(!unconfigured_printers_.contains(printer.id())); + configured_printers_.insert(printer.id()); +} + +void AutomaticUsbPrinterConfigurer::PruneRemovedAutomaticPrinters( + const std::vector<Printer>& automatic_printers) { + PruneRemovedPrinters(automatic_printers, /*use_configured_printers=*/true); +} + +void AutomaticUsbPrinterConfigurer::PruneRemovedDiscoveredPrinters( + const std::vector<Printer>& discovered_printers) { + PruneRemovedPrinters(discovered_printers, /*use_configured_printers=*/false); } void AutomaticUsbPrinterConfigurer::PruneRemovedPrinters( - const std::vector<Printer>& automatic_printers) { - for (auto it = printers_.begin(); it != printers_.end();) { - if (!IsInAutomaticList(*it, automatic_printers)) { + const std::vector<Printer>& current_printers, + bool use_configured_printers) { + auto& printers = + use_configured_printers ? configured_printers_ : unconfigured_printers_; + for (auto it = printers.begin(); it != printers.end();) { + if (!IsPrinterIdInList(*it, current_printers)) { notification_controller_->RemoveNotification(*it); - it = printers_.erase(it); + it = printers.erase(it); } else { ++it; }
diff --git a/chrome/browser/chromeos/printing/automatic_usb_printer_configurer.h b/chrome/browser/chromeos/printing/automatic_usb_printer_configurer.h index 4ffd917..2f1bd132 100644 --- a/chrome/browser/chromeos/printing/automatic_usb_printer_configurer.h +++ b/chrome/browser/chromeos/printing/automatic_usb_printer_configurer.h
@@ -37,8 +37,6 @@ private: FRIEND_TEST_ALL_PREFIXES(AutomaticUsbPrinterConfigurerTest, UsbPrinterAddedToSet); - FRIEND_TEST_ALL_PREFIXES(AutomaticUsbPrinterConfigurerTest, - UsbPrinterRemovedFromSet); // Uses |printer_configurer_| to setup |printer| if it is not yet setup. void SetupPrinter(const Printer& printer); @@ -46,19 +44,33 @@ // Callback for PrinterConfiguer::SetUpPrinter(). void OnSetupComplete(const Printer& printer, PrinterSetupResult result); - // Completes the configuration for |printer|. Saves printer in |printers_|. + // Completes the configuration for |printer|. Saves printer in + // |configured_printers_|. void CompleteConfiguration(const Printer& printer); - // Removes any printers from |printers_| that are no longer in + // Removes any printers from |configured_printers_| that are no longer in // |automatic_printers|. - void PruneRemovedPrinters(const std::vector<Printer>& automatic_printers); + void PruneRemovedAutomaticPrinters( + const std::vector<Printer>& automatic_printers); + + // Removes any printers from |unconfigured_printers_| that are no longer in + // |discovered_printers|. + void PruneRemovedDiscoveredPrinters( + const std::vector<Printer>& discovered_printers); + + // Helper function that removes printers that are no longer in + // |current_printers|. If |use_configured_printers|, |configured_printers_| is + // pruned. Otherwise, |unconfigured_printers_| is pruned. + void PruneRemovedPrinters(const std::vector<Printer>& current_printers, + bool use_configured_printers); SEQUENCE_CHECKER(sequence_); std::unique_ptr<PrinterConfigurer> printer_configurer_; PrinterInstallationManager* installation_manager_; // Not owned. UsbPrinterNotificationController* notification_controller_; // Not owned. - base::flat_set<std::string> printers_; + base::flat_set<std::string> configured_printers_; + base::flat_set<std::string> unconfigured_printers_; base::WeakPtrFactory<AutomaticUsbPrinterConfigurer> weak_factory_;
diff --git a/chrome/browser/chromeos/printing/automatic_usb_printer_configurer_unittest.cc b/chrome/browser/chromeos/printing/automatic_usb_printer_configurer_unittest.cc index 4e8dd7a..d34538da 100644 --- a/chrome/browser/chromeos/printing/automatic_usb_printer_configurer_unittest.cc +++ b/chrome/browser/chromeos/printing/automatic_usb_printer_configurer_unittest.cc
@@ -65,6 +65,10 @@ RemovePrinter(PrinterClass::kAutomatic, printer_id); } + void RemoveDiscoveredPrinter(const std::string& printer_id) { + RemovePrinter(PrinterClass::kDiscovered, printer_id); + } + private: // Add |printer| to the corresponding list in |printers_| bases on the given // |printer_class|. @@ -76,7 +80,7 @@ // Remove |printer_id| from |printer_class|. void RemovePrinter(PrinterClass printer_class, const std::string& printer_id) { - printers_.Remove(PrinterClass::kAutomatic, printer_id); + printers_.Remove(printer_class, printer_id); observer_->OnPrintersChanged(printer_class, printers_.Get(printer_class)); } @@ -117,15 +121,15 @@ // Manipulation functions bool IsConfigured(const std::string& printer_id) const { - return configured_.contains(printer_id); + return configured_printers_.contains(printer_id); } void MarkConfigured(const std::string& printer_id) { - configured_.insert(printer_id); + configured_printers_.insert(printer_id); } private: - base::flat_set<std::string> configured_; + base::flat_set<std::string> configured_printers_; }; class FakeUsbPrinterNotificationController @@ -143,7 +147,7 @@ } void ShowConfigurationNotification(const Printer& printer) override { - NOTIMPLEMENTED(); + open_notifications_.insert(printer.id()); } void RemoveNotification(const std::string& printer_id) override { @@ -237,8 +241,8 @@ const std::string printer_id = "id"; const Printer printer = CreateUsbPrinter(printer_id); - // Adding an automatic USB printer should result in the printer becoming - // configured and getting marked as installed. + // Adding a discovered USB printer should not result in the printer getting + // installed. fake_observable_printers_manager_.AddNearbyDiscoveredPrinter(printer); EXPECT_FALSE(fake_installation_manager_->IsPrinterInstalled(printer)); @@ -260,30 +264,44 @@ } TEST_F(AutomaticUsbPrinterConfigurerTest, UsbPrinterAddedToSet) { - const std::string printer_id = "id"; - const Printer printer = CreateUsbPrinter(printer_id); + const std::string automatic_printer_id = "auto_id"; + const Printer automatic_printer = CreateUsbPrinter(automatic_printer_id); + + const std::string discovered_printer_id = "disco_id"; + const Printer discovered_printer = CreateUsbPrinter(discovered_printer_id); // Adding an automatic USB printer should result in the printer getting added - // to |auto_usb_printer_configurer_::printers_|. - fake_observable_printers_manager_.AddNearbyAutomaticPrinter(printer); + // to |auto_usb_printer_configurer_::configured_printers_|. + fake_observable_printers_manager_.AddNearbyAutomaticPrinter( + automatic_printer); - EXPECT_EQ(1u, auto_usb_printer_configurer_->printers_.size()); - EXPECT_TRUE(auto_usb_printer_configurer_->printers_.contains(printer_id)); -} + EXPECT_TRUE(auto_usb_printer_configurer_->configured_printers_.contains( + automatic_printer_id)); -TEST_F(AutomaticUsbPrinterConfigurerTest, UsbPrinterRemovedFromSet) { - const std::string printer_id = "id"; - const Printer printer = CreateUsbPrinter(printer_id); + // Adding a discovered USB printer should result in the printer getting added + // to |auto_usb_printer_configurer_::unconfigured_printers_|. + fake_observable_printers_manager_.AddNearbyDiscoveredPrinter( + discovered_printer); - fake_observable_printers_manager_.AddNearbyAutomaticPrinter(printer); + EXPECT_TRUE(auto_usb_printer_configurer_->unconfigured_printers_.contains( + discovered_printer_id)); - EXPECT_EQ(1u, auto_usb_printer_configurer_->printers_.size()); + EXPECT_EQ(1u, auto_usb_printer_configurer_->configured_printers_.size()); + EXPECT_EQ(1u, auto_usb_printer_configurer_->unconfigured_printers_.size()); // Removing the automatic printer should result in the printer getting - // removed from |auto_usb_printer_configurer_::printers_|. - fake_observable_printers_manager_.RemoveAutomaticPrinter(printer_id); + // removed from |auto_usb_printer_configurer_::unconfigured_printers_|. + fake_observable_printers_manager_.RemoveDiscoveredPrinter( + discovered_printer_id); - EXPECT_EQ(0u, auto_usb_printer_configurer_->printers_.size()); + EXPECT_EQ(0u, auto_usb_printer_configurer_->unconfigured_printers_.size()); + + // Removing the automatic printer should result in the printer getting + // removed from |auto_usb_printer_configurer_::configured_printers_|. + fake_observable_printers_manager_.RemoveAutomaticPrinter( + automatic_printer_id); + + EXPECT_EQ(0u, auto_usb_printer_configurer_->configured_printers_.size()); } TEST_F(AutomaticUsbPrinterConfigurerTest, NotificationOpenedForNewAutomatic) { @@ -323,4 +341,13 @@ EXPECT_FALSE(fake_notification_controller_->IsNotification(printer_id)); } +TEST_F(AutomaticUsbPrinterConfigurerTest, NotificationOpenedForNewDiscovered) { + const std::string printer_id = "id"; + const Printer printer = CreateUsbPrinter(printer_id); + + fake_observable_printers_manager_.AddNearbyAutomaticPrinter(printer); + + EXPECT_TRUE(fake_notification_controller_->IsNotification(printer_id)); +} + } // namespace chromeos
diff --git a/chrome/browser/chromeos/printing/cups_printers_manager_unittest.cc b/chrome/browser/chromeos/printing/cups_printers_manager_unittest.cc index 6175e63c..4b65ae9b 100644 --- a/chrome/browser/chromeos/printing/cups_printers_manager_unittest.cc +++ b/chrome/browser/chromeos/printing/cups_printers_manager_unittest.cc
@@ -307,20 +307,31 @@ NOTIMPLEMENTED(); } void ShowConfigurationNotification(const Printer& printer) override { - NOTIMPLEMENTED(); + configuration_notifications_.insert(printer.id()); } void ShowSavedNotification(const Printer& printer) override { - open_notifications_.insert(printer.id()); + saved_notifications_.insert(printer.id()); } void RemoveNotification(const std::string& printer_id) override { - open_notifications_.erase(printer_id); + saved_notifications_.erase(printer_id); + configuration_notifications_.erase(printer_id); } bool IsNotification(const std::string& printer_id) const override { - return open_notifications_.contains(printer_id); + return configuration_notifications_.contains(printer_id) || + saved_notifications_.contains(printer_id); + } + + bool IsSavedNotification(const std::string& printer_id) const { + return saved_notifications_.contains(printer_id); + } + + bool IsConfigurationNotification(const std::string& printer_id) const { + return configuration_notifications_.contains(printer_id); } private: - base::flat_set<std::string> open_notifications_; + base::flat_set<std::string> saved_notifications_; + base::flat_set<std::string> configuration_notifications_; }; class CupsPrintersManagerTest : public testing::Test, @@ -835,5 +846,32 @@ EXPECT_FALSE(printer_configurer_->IsConfigured("Automatic")); } +TEST_F(CupsPrintersManagerTest, DetectedUsbPrinterConfigurationNotification) { + auto discovered_printer = MakeDiscoveredPrinter("Discovered"); + discovered_printer.printer.set_uri("usb:"); + + usb_detector_->AddDetections({discovered_printer}); + scoped_task_environment_.RunUntilIdle(); + + EXPECT_TRUE(usb_notif_controller_->IsConfigurationNotification("Discovered")); + + usb_detector_->RemoveDetections({"Discovered"}); + + EXPECT_FALSE( + usb_notif_controller_->IsConfigurationNotification("Discovered")); +} + +TEST_F(CupsPrintersManagerTest, + DetectedZeroconfDiscoveredPrinterNoNotification) { + auto discovered_printer = MakeDiscoveredPrinter("Discovered"); + discovered_printer.printer.set_uri("ipp:"); + + zeroconf_detector_->AddDetections({discovered_printer}); + scoped_task_environment_.RunUntilIdle(); + + EXPECT_FALSE( + usb_notif_controller_->IsConfigurationNotification("Discovered")); +} + } // namespace } // namespace chromeos
diff --git a/chrome/browser/chromeos/printing/doc/cups_printers_settings_page.md b/chrome/browser/chromeos/printing/doc/cups_printers_settings_page.md index 5ce556b..78100cef 100644 --- a/chrome/browser/chromeos/printing/doc/cups_printers_settings_page.md +++ b/chrome/browser/chromeos/printing/doc/cups_printers_settings_page.md
@@ -100,6 +100,7 @@ `getPrinterPpdManufacturerAndModel` | `HandleGetPrinterPpdManufacturerAndModel` `addDiscoveredPrinter` | `HandleAddDiscoveredPrinter` `cancelPrinterSetup` | `HandleSetUpCancel` +`getEulaUrl` | `HandleGetEulaUrl` ## Javascript Listeners
diff --git a/chrome/browser/devtools/devtools_file_helper.cc b/chrome/browser/devtools/devtools_file_helper.cc index 7497a31..b9a627c 100644 --- a/chrome/browser/devtools/devtools_file_helper.cc +++ b/chrome/browser/devtools/devtools_file_helper.cc
@@ -145,24 +145,25 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); CHECK(web_contents->GetURL().SchemeIs(content::kChromeDevToolsScheme)); std::string root_name(kRootName); - std::string file_system_id = isolated_context()->RegisterFileSystemForPath( - storage::kFileSystemTypeNativeLocal, std::string(), path, &root_name); + storage::IsolatedContext::ScopedFSHandle file_system = + isolated_context()->RegisterFileSystemForPath( + storage::kFileSystemTypeNativeLocal, std::string(), path, &root_name); content::ChildProcessSecurityPolicy* policy = content::ChildProcessSecurityPolicy::GetInstance(); RenderViewHost* render_view_host = web_contents->GetRenderViewHost(); int renderer_id = render_view_host->GetProcess()->GetID(); - policy->GrantReadFileSystem(renderer_id, file_system_id); - policy->GrantWriteFileSystem(renderer_id, file_system_id); - policy->GrantCreateFileForFileSystem(renderer_id, file_system_id); - policy->GrantDeleteFromFileSystem(renderer_id, file_system_id); + policy->GrantReadFileSystem(renderer_id, file_system.id()); + policy->GrantWriteFileSystem(renderer_id, file_system.id()); + policy->GrantCreateFileForFileSystem(renderer_id, file_system.id()); + policy->GrantDeleteFromFileSystem(renderer_id, file_system.id()); // We only need file level access for reading FileEntries. Saving FileEntries // just needs the file system to have read/write access, which is granted // above if required. if (!policy->CanReadFile(renderer_id, path)) policy->GrantReadFile(renderer_id, path); - return file_system_id; + return file_system.id(); } DevToolsFileHelper::FileSystem CreateFileSystemStruct(
diff --git a/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc b/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc index 8f148a77..b440c80 100644 --- a/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc +++ b/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc
@@ -167,12 +167,12 @@ // Set a fixed register name, as the automatic one would leak the mount point // directory. std::string register_name = "fs"; - const std::string file_system_id = + const storage::IsolatedContext::ScopedFSHandle file_system = isolated_context->RegisterFileSystemForPath( storage::kFileSystemTypeNativeForPlatformApp, std::string() /* file_system_id */, original_url.path(), ®ister_name); - if (file_system_id.empty()) { + if (!file_system.is_valid()) { error_callback.Run(kSecurityError); return; } @@ -187,18 +187,18 @@ const auto process_id = requester->source_process_id(); // Read-only permisisons. policy->GrantReadFile(process_id, volume->mount_path()); - policy->GrantReadFileSystem(process_id, file_system_id); + policy->GrantReadFileSystem(process_id, file_system.id()); // Additional write permissions. if (writable) { policy->GrantCreateReadWriteFile(process_id, volume->mount_path()); policy->GrantCopyInto(process_id, volume->mount_path()); - policy->GrantWriteFileSystem(process_id, file_system_id); - policy->GrantDeleteFromFileSystem(process_id, file_system_id); - policy->GrantCreateFileForFileSystem(process_id, file_system_id); + policy->GrantWriteFileSystem(process_id, file_system.id()); + policy->GrantDeleteFromFileSystem(process_id, file_system.id()); + policy->GrantCreateFileForFileSystem(process_id, file_system.id()); } - success_callback.Run(file_system_id, register_name); + success_callback.Run(file_system.id(), register_name); } } // namespace
diff --git a/chrome/browser/media/webrtc/webrtc_logging_handler_host.cc b/chrome/browser/media/webrtc/webrtc_logging_handler_host.cc index d0bfe101..9788a4a 100644 --- a/chrome/browser/media/webrtc/webrtc_logging_handler_host.cc +++ b/chrome/browser/media/webrtc/webrtc_logging_handler_host.cc
@@ -312,20 +312,21 @@ DCHECK(isolated_context); std::string registered_name; - std::string filesystem_id = isolated_context->RegisterFileSystemForPath( - storage::kFileSystemTypeNativeLocal, std::string(), logs_path, - ®istered_name); + storage::IsolatedContext::ScopedFSHandle file_system = + isolated_context->RegisterFileSystemForPath( + storage::kFileSystemTypeNativeLocal, std::string(), logs_path, + ®istered_name); // Only granting read and delete access to reduce contention with // webrtcLogging APIs that modify files in that folder. content::ChildProcessSecurityPolicy* policy = content::ChildProcessSecurityPolicy::GetInstance(); - policy->GrantReadFileSystem(render_process_id_, filesystem_id); + policy->GrantReadFileSystem(render_process_id_, file_system.id()); // Delete is needed to prevent accumulation of files. - policy->GrantDeleteFromFileSystem(render_process_id_, filesystem_id); + policy->GrantDeleteFromFileSystem(render_process_id_, file_system.id()); base::PostTaskWithTraits( FROM_HERE, {BrowserThread::UI}, - base::BindOnce(callback, filesystem_id, registered_name)); + base::BindOnce(callback, file_system.id(), registered_name)); } #endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
diff --git a/chrome/browser/media_galleries/fileapi/media_file_validator_browsertest.cc b/chrome/browser/media_galleries/fileapi/media_file_validator_browsertest.cc index f1e7f00..dd6919e 100644 --- a/chrome/browser/media_galleries/fileapi/media_file_validator_browsertest.cc +++ b/chrome/browser/media_galleries/fileapi/media_file_validator_browsertest.cc
@@ -153,18 +153,16 @@ base::FilePath dest_path = base.AppendASCII("dest_fs"); ASSERT_TRUE(base::CreateDirectory(dest_path)); - std::string dest_fsid = + dest_fs_ = storage::IsolatedContext::GetInstance()->RegisterFileSystemForPath( - storage::kFileSystemTypeNativeMedia, - std::string(), - dest_path, + storage::kFileSystemTypeNativeMedia, std::string(), dest_path, NULL); size_t extension_index = filename.find_last_of("."); ASSERT_NE(std::string::npos, extension_index); std::string extension = filename.substr(extension_index); std::string dest_root_fs_url = storage::GetIsolatedFileSystemRootURIString( - GURL(kOrigin), dest_fsid, "dest_fs/"); + GURL(kOrigin), dest_fs_.id(), "dest_fs/"); move_dest_ = file_system_context_->CrackURL(GURL( dest_root_fs_url + "move_dest" + extension)); @@ -262,6 +260,7 @@ storage::FileSystemURL move_src_; storage::FileSystemURL move_dest_; + storage::IsolatedContext::ScopedFSHandle dest_fs_; base::OnceClosure quit_closure_; scoped_refptr<base::SequencedTaskRunner> file_system_runner_;
diff --git a/chrome/browser/media_galleries/fileapi/native_media_file_util_unittest.cc b/chrome/browser/media_galleries/fileapi/native_media_file_util_unittest.cc index 751cadb8..dd621fd 100644 --- a/chrome/browser/media_galleries/fileapi/native_media_file_util_unittest.cc +++ b/chrome/browser/media_galleries/fileapi/native_media_file_util_unittest.cc
@@ -54,23 +54,23 @@ }; const FilteringTestCase kFilteringTestCases[] = { - // Directory should always be visible. - { FPL("hoge"), true, true, false, NULL }, - { FPL("fuga.jpg"), true, true, false, NULL }, - { FPL("piyo.txt"), true, true, false, NULL }, - { FPL("moga.cod"), true, true, false, NULL }, + // Directory should always be visible. + {FPL("hoge"), true, true, false, NULL}, + {FPL("fuga.jpg"), true, true, false, NULL}, + {FPL("piyo.txt"), true, true, false, NULL}, + {FPL("moga.cod"), true, true, false, NULL}, - // File should be visible if it's a supported media file. - // File without extension. - { FPL("foo"), false, false, false, "abc" }, - // Supported media file. - { FPL("bar.jpg"), false, true, true, "\xFF\xD8\xFF" }, - // Unsupported masquerading file. - { FPL("sna.jpg"), false, true, false, "abc" }, - // Non-media file. - { FPL("baz.txt"), false, false, false, "abc" }, - // Unsupported media file. - { FPL("foobar.cod"), false, false, false, "abc" }, + // File should be visible if it's a supported media file. + // File without extension. + {FPL("foo"), false, false, false, "abc"}, + // Supported media file. + {FPL("bar.jpg"), false, true, true, "\xFF\xD8\xFF"}, + // Unsupported masquerading file. + {FPL("sna.jpg"), false, true, false, "abc"}, + // Non-media file. + {FPL("baz.txt"), false, false, false, "abc"}, + // Unsupported media file. + {FPL("foobar.cod"), false, false, false, "abc"}, }; void ExpectEqHelper(const std::string& test_name, @@ -143,14 +143,12 @@ std::vector<storage::URLRequestAutoMountHandler>(), data_dir_.GetPath(), content::CreateAllowFileAccessOptions()); - filesystem_id_ = isolated_context()->RegisterFileSystemForPath( + filesystem_ = isolated_context()->RegisterFileSystemForPath( storage::kFileSystemTypeNativeMedia, std::string(), root_path(), NULL); - - isolated_context()->AddReference(filesystem_id_); + filesystem_id_ = filesystem_.id(); } void TearDown() override { - isolated_context()->RemoveReference(filesystem_id_); file_system_context_ = NULL; } @@ -161,8 +159,7 @@ FileSystemURL CreateURL(const base::FilePath::CharType* test_case_path) { return file_system_context_->CreateCrackedFileSystemURL( - origin(), - storage::kFileSystemTypeIsolated, + origin(), storage::kFileSystemTypeIsolated, GetVirtualPath(test_case_path)); } @@ -176,14 +173,12 @@ base::FilePath GetVirtualPath( const base::FilePath::CharType* test_case_path) { - return base::FilePath::FromUTF8Unsafe(filesystem_id_). - Append(FPL("Media Directory")). - Append(base::FilePath(test_case_path)); + return base::FilePath::FromUTF8Unsafe(filesystem_id_) + .Append(FPL("Media Directory")) + .Append(base::FilePath(test_case_path)); } - GURL origin() { - return GURL("http://example.com"); - } + GURL origin() { return GURL("http://example.com"); } storage::FileSystemType type() { return storage::kFileSystemTypeNativeMedia; } @@ -198,6 +193,7 @@ scoped_refptr<storage::FileSystemContext> file_system_context_; std::string filesystem_id_; + storage::IsolatedContext::ScopedFSHandle filesystem_; DISALLOW_COPY_AND_ASSIGN(NativeMediaFileUtilTest); }; @@ -209,10 +205,9 @@ for (size_t i = 0; i < base::size(kFilteringTestCases); ++i) { FileSystemURL url = CreateURL(kFilteringTestCases[i].path); - base::File::Error expectation = - kFilteringTestCases[i].visible ? - base::File::FILE_OK : - base::File::FILE_ERROR_NOT_FOUND; + base::File::Error expectation = kFilteringTestCases[i].visible + ? base::File::FILE_OK + : base::File::FILE_ERROR_NOT_FOUND; std::string test_name = base::StringPrintf("DirectoryExistsAndFileExistsFiltering %" PRIuS, i); @@ -260,10 +255,9 @@ std::string test_name = base::StringPrintf( "CreateFileAndCreateDirectoryFiltering run %d, test %" PRIuS, loop_count, i); - base::File::Error expectation = - kFilteringTestCases[i].visible ? - base::File::FILE_OK : - base::File::FILE_ERROR_SECURITY; + base::File::Error expectation = kFilteringTestCases[i].visible + ? base::File::FILE_OK + : base::File::FILE_ERROR_SECURITY; operation_runner()->CreateDirectory( url, false, false, base::Bind(&ExpectEqHelper, test_name, expectation)); @@ -349,10 +343,9 @@ // handled above. // If the destination path does not exist and is not visible, then // creating it would be a security violation. - expectation = - kFilteringTestCases[i].visible ? - base::File::FILE_OK : - base::File::FILE_ERROR_SECURITY; + expectation = kFilteringTestCases[i].visible + ? base::File::FILE_OK + : base::File::FILE_ERROR_SECURITY; } else { if (!kFilteringTestCases[i].visible) { // If the destination path exist and is not visible, then to the copy @@ -407,9 +400,7 @@ expectation = base::File::FILE_ERROR_INVALID_OPERATION; } operation_runner()->Move( - url, - dest_url, - storage::FileSystemOperation::OPTION_NONE, + url, dest_url, storage::FileSystemOperation::OPTION_NONE, base::Bind(&ExpectEqHelper, test_name, expectation)); content::RunAllTasksUntilIdle(); } @@ -454,10 +445,9 @@ // handled above. // If the destination path does not exist and is not visible, then // creating it would be a security violation. - expectation = - kFilteringTestCases[i].visible ? - base::File::FILE_OK : - base::File::FILE_ERROR_SECURITY; + expectation = kFilteringTestCases[i].visible + ? base::File::FILE_OK + : base::File::FILE_ERROR_SECURITY; } else { if (!kFilteringTestCases[i].visible) { // If the destination path exist and is not visible, then to the move @@ -473,9 +463,7 @@ } } operation_runner()->Move( - src_url, - url, - storage::FileSystemOperation::OPTION_NONE, + src_url, url, storage::FileSystemOperation::OPTION_NONE, base::Bind(&ExpectEqHelper, test_name, expectation)); content::RunAllTasksUntilIdle(); } @@ -560,8 +548,8 @@ else expected_error = base::File::FILE_ERROR_SECURITY; error = base::File::FILE_ERROR_FAILED; - operation_runner()->CreateSnapshotFile(url, - base::Bind(CreateSnapshotCallback, &error)); + operation_runner()->CreateSnapshotFile( + url, base::Bind(CreateSnapshotCallback, &error)); content::RunAllTasksUntilIdle(); ASSERT_EQ(expected_error, error); }
diff --git a/chrome/browser/notifications/scheduler/notification_scheduler.cc b/chrome/browser/notifications/scheduler/notification_scheduler.cc index 8985f92..f1375a7 100644 --- a/chrome/browser/notifications/scheduler/notification_scheduler.cc +++ b/chrome/browser/notifications/scheduler/notification_scheduler.cc
@@ -37,16 +37,19 @@ // Initializes subsystems in notification scheduler, |callback| will be // invoked if all initializations finished or anyone of them failed. The // object should be destroyed along with the |callback|. - void Init(NotificationSchedulerContext* context, InitCallback callback) { + void Init(NotificationSchedulerContext* context, + ScheduledNotificationManager::Delegate* delegate, + InitCallback callback) { callback_ = std::move(callback); context->icon_store()->Init(base::BindOnce( &InitHelper::OnIconStoreInitialized, weak_ptr_factory_.GetWeakPtr())); context->impression_tracker()->Init( base::BindOnce(&InitHelper::OnImpressionTrackerInitialized, weak_ptr_factory_.GetWeakPtr())); + context->notification_manager()->Init( - base::BindOnce(&InitHelper::OnNotificationManagerInitialized, - weak_ptr_factory_.GetWeakPtr())); + delegate, base::BindOnce(&InitHelper::OnNotificationManagerInitialized, + weak_ptr_factory_.GetWeakPtr())); } private: @@ -106,7 +109,7 @@ auto helper = std::make_unique<InitHelper>(); auto* helper_ptr = helper.get(); helper_ptr->Init( - context_.get(), + context_.get(), this, base::BindOnce(&NotificationSchedulerImpl::OnInitialized, weak_ptr_factory_.GetWeakPtr(), std::move(helper), std::move(init_callback)));
diff --git a/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc b/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc index af11260..abe5f4b5 100644 --- a/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc +++ b/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/notifications/scheduler/notification_background_task_scheduler.h" #include "chrome/browser/notifications/scheduler/notification_schedule_service_impl.h" #include "chrome/browser/notifications/scheduler/notification_scheduler_context.h" +#include "chrome/browser/notifications/scheduler/notification_store.h" #include "chrome/browser/notifications/scheduler/scheduled_notification_manager.h" #include "chrome/browser/notifications/scheduler/scheduler_config.h" #include "components/leveldb_proto/public/proto_database_provider.h" @@ -26,6 +27,8 @@ const base::FilePath::CharType kImpressionDBName[] = FILE_PATH_LITERAL("ImpressionDB"); const base::FilePath::CharType kIconDBName[] = FILE_PATH_LITERAL("IconDB"); +const base::FilePath::CharType kNotificationDBName[] = + FILE_PATH_LITERAL("NotificationDB"); } // namespace KeyedService* CreateNotificationScheduleService( @@ -54,13 +57,24 @@ auto impression_tracker = std::make_unique<ImpressionHistoryTrackerImpl>( *config.get(), std::move(impression_store)); - // TODO(xingliu): Build notification store. + // Build notification store. + base::FilePath notification_store_dir = + storage_dir.Append(kNotificationDBName); + auto notification_db = db_provider->GetDB<proto::NotificationEntry, + notifications::NotificationEntry>( + leveldb_proto::ProtoDbType::NOTIFICATION_SCHEDULER_NOTIFICATION_STORE, + notification_store_dir, task_runner); + auto notification_store = + std::make_unique<NotificationStore>(std::move(notification_db)); + std::unique_ptr<ScheduledNotificationManager> notification_manager; + notification_manager->Create(std::move(notification_store)); auto context = std::make_unique<NotificationSchedulerContext>( std::move(background_task_scheduler), std::move(icon_store), std::move(impression_tracker), std::move(notification_manager), DisplayDecider::Create(), std::move(config)); + auto scheduler = NotificationScheduler::Create(std::move(context)); auto init_aware_scheduler = std::make_unique<InitAwareNotificationScheduler>(std::move(scheduler));
diff --git a/chrome/browser/notifications/scheduler/scheduled_notification_manager.cc b/chrome/browser/notifications/scheduler/scheduled_notification_manager.cc index 3b1badb..cd3bdf0 100644 --- a/chrome/browser/notifications/scheduler/scheduled_notification_manager.cc +++ b/chrome/browser/notifications/scheduler/scheduled_notification_manager.cc
@@ -27,13 +27,13 @@ public: using Store = std::unique_ptr<CollectionStore<NotificationEntry>>; - ScheduledNotificationManagerImpl(Store store, Delegate* delegate) - : store_(std::move(store)), - delegate_(delegate), - weak_ptr_factory_(this) {} + ScheduledNotificationManagerImpl(Store store) + : store_(std::move(store)), delegate_(nullptr), weak_ptr_factory_(this) {} private: - void Init(InitCallback callback) override { + void Init(Delegate* delegate, InitCallback callback) override { + DCHECK(!delegate_); + delegate_ = delegate; store_->InitAndLoad( base::BindOnce(&ScheduledNotificationManagerImpl::OnStoreInitialized, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); @@ -127,10 +127,8 @@ // static std::unique_ptr<ScheduledNotificationManager> ScheduledNotificationManager::Create( - std::unique_ptr<CollectionStore<NotificationEntry>> store, - Delegate* delegate) { - return std::make_unique<ScheduledNotificationManagerImpl>(std::move(store), - delegate); + std::unique_ptr<CollectionStore<NotificationEntry>> store) { + return std::make_unique<ScheduledNotificationManagerImpl>(std::move(store)); } ScheduledNotificationManager::ScheduledNotificationManager() = default;
diff --git a/chrome/browser/notifications/scheduler/scheduled_notification_manager.h b/chrome/browser/notifications/scheduler/scheduled_notification_manager.h index 01293a5..00d3716 100644 --- a/chrome/browser/notifications/scheduler/scheduled_notification_manager.h +++ b/chrome/browser/notifications/scheduler/scheduled_notification_manager.h
@@ -42,11 +42,10 @@ // Creates the instance. static std::unique_ptr<ScheduledNotificationManager> Create( - std::unique_ptr<CollectionStore<NotificationEntry>> store, - Delegate* delegate); + std::unique_ptr<CollectionStore<NotificationEntry>> store); // Initializes the notification store. - virtual void Init(InitCallback callback) = 0; + virtual void Init(Delegate* delegate, InitCallback callback) = 0; // Adds a new notification. virtual void ScheduleNotification(
diff --git a/chrome/browser/notifications/scheduler/scheduled_notification_manager_unittest.cc b/chrome/browser/notifications/scheduler/scheduled_notification_manager_unittest.cc index 43d350a9..0a6de34 100644 --- a/chrome/browser/notifications/scheduler/scheduled_notification_manager_unittest.cc +++ b/chrome/browser/notifications/scheduler/scheduled_notification_manager_unittest.cc
@@ -67,8 +67,7 @@ delegate_ = std::make_unique<MockDelegate>(); auto store = std::make_unique<MockNotificationStore>(); store_ = store.get(); - manager_ = - ScheduledNotificationManager::Create(std::move(store), delegate_.get()); + manager_ = ScheduledNotificationManager::Create(std::move(store)); } protected: @@ -93,12 +92,13 @@ std::move(cb).Run(true, std::move(entries)); })); base::RunLoop loop; - manager()->Init(base::BindOnce( - [](base::RepeatingClosure closure, bool success) { - EXPECT_TRUE(success); - std::move(closure).Run(); - }, - loop.QuitClosure())); + manager()->Init(delegate(), + base::BindOnce( + [](base::RepeatingClosure closure, bool success) { + EXPECT_TRUE(success); + std::move(closure).Run(); + }, + loop.QuitClosure())); loop.Run(); } @@ -118,13 +118,14 @@ })); base::RunLoop loop; - manager()->Init(base::BindOnce( - [](base::RepeatingClosure closure, bool success) { - // Expected to receive error. - EXPECT_FALSE(success); - std::move(closure).Run(); - }, - loop.QuitClosure())); + manager()->Init(delegate(), + base::BindOnce( + [](base::RepeatingClosure closure, bool success) { + // Expected to receive error. + EXPECT_FALSE(success); + std::move(closure).Run(); + }, + loop.QuitClosure())); loop.Run(); }
diff --git a/chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.cc b/chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.cc index 5e468b2..0d083bb 100644 --- a/chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.cc +++ b/chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.cc
@@ -102,14 +102,14 @@ return profile_manager->GetProfile(profile_directory_); } -std::string PepperIsolatedFileSystemMessageFilter::CreateCrxFileSystem( - Profile* profile) { +storage::IsolatedContext::ScopedFSHandle +PepperIsolatedFileSystemMessageFilter::CreateCrxFileSystem(Profile* profile) { #if BUILDFLAG(ENABLE_EXTENSIONS) const extensions::Extension* extension = extensions::ExtensionRegistry::Get(profile)->enabled_extensions().GetByID( document_url_.host()); if (!extension) - return std::string(); + return storage::IsolatedContext::ScopedFSHandle(); // First level directory for isolated filesystem to lookup. std::string kFirstLevelDirectory("crxfs"); @@ -119,7 +119,7 @@ extension->path(), &kFirstLevelDirectory); #else - return std::string(); + return storage::IsolatedContext::ScopedFSHandle(); #endif } @@ -160,8 +160,9 @@ // TODO(raymes): When we remove FileSystem from the renderer, we should create // a pending PepperFileSystemBrowserHost here with the fsid and send the // pending host ID back to the plugin. - const std::string fsid = CreateCrxFileSystem(profile); - if (fsid.empty()) { + const storage::IsolatedContext::ScopedFSHandle fs = + CreateCrxFileSystem(profile); + if (!fs.is_valid()) { context->reply_msg = PpapiPluginMsg_IsolatedFileSystem_BrowserOpenReply(std::string()); return PP_ERROR_NOTSUPPORTED; @@ -170,9 +171,10 @@ // Grant readonly access of isolated filesystem to renderer process. content::ChildProcessSecurityPolicy* policy = content::ChildProcessSecurityPolicy::GetInstance(); - policy->GrantReadFileSystem(render_process_id_, fsid); + policy->GrantReadFileSystem(render_process_id_, fs.id()); - context->reply_msg = PpapiPluginMsg_IsolatedFileSystem_BrowserOpenReply(fsid); + context->reply_msg = + PpapiPluginMsg_IsolatedFileSystem_BrowserOpenReply(fs.id()); return PP_OK; #else return PP_ERROR_NOTSUPPORTED;
diff --git a/chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.h b/chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.h index ca7f87b9..1d5ff1f 100644 --- a/chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.h +++ b/chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.h
@@ -17,6 +17,7 @@ #include "ppapi/c/private/ppb_isolated_file_system_private.h" #include "ppapi/host/resource_host.h" #include "ppapi/host/resource_message_filter.h" +#include "storage/browser/fileapi/isolated_context.h" #include "url/gurl.h" class Profile; @@ -58,7 +59,8 @@ // Returns filesystem id of isolated filesystem if valid, or empty string // otherwise. This must run on the UI thread because ProfileManager only // allows access on that thread. - std::string CreateCrxFileSystem(Profile* profile); + storage::IsolatedContext::ScopedFSHandle CreateCrxFileSystem( + Profile* profile); int32_t OnOpenFileSystem(ppapi::host::HostMessageContext* context, PP_IsolatedFileSystemType_Private type);
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/settings.js b/chrome/browser/resources/chromeos/camera/src/js/views/settings.js index 641fad31..1c1c916 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/views/settings.js +++ b/chrome/browser/resources/chromeos/camera/src/js/views/settings.js
@@ -307,13 +307,33 @@ // Update external camera settings this.externalSettings_ = externalSettings; - this.resMenu_.querySelectorAll('.menu-item.external-camera') - .forEach((element) => element.parentNode.removeChild(element)); - externalSettings.forEach(([deviceId, photoRs, videoRs]) => { + // To prevent losing focus on item already exist before update, locate + // focused item in both previous and current list, pop out all items in + // previous list except those having same deviceId as focused one and + // recreate all other items from current list. + const prevFocus = + this.resMenu_.querySelector('.menu-item.external-camera:focus'); + const prevFId = prevFocus && prevFocus.dataset.deviceId; + const focusIdx = externalSettings.findIndex(([id]) => id === prevFId); + const fTitle = + this.resMenu_.querySelector(`.menu-item[data-device-id="${prevFId}"]`); + const focusedId = focusIdx === -1 ? null : prevFId; + + this.resMenu_.querySelectorAll('.menu-item.external-camera') + .forEach( + (element) => element.dataset.deviceId !== focusedId && + element.parentNode.removeChild(element)); + + externalSettings.forEach(([deviceId, photoRs, videoRs], index) => { + if (deviceId === focusedId) { + return; + } const extItem = document.importNode(this.extcamItemTempl_.content, true); - const [photoItem, videoItem] = extItem.querySelectorAll('.resol-item'); - photoItem.dataset.deviceId = videoItem.dataset.deviceId = deviceId; + const [titleItem, photoItem, videoItem] = + extItem.querySelectorAll('.menu-item'); + titleItem.dataset.deviceId = photoItem.dataset.deviceId = + videoItem.dataset.deviceId = deviceId; checkMulti(photoItem, photoRs, this.photoOptTextTempl_); checkMulti(videoItem, videoRs, this.videoOptTextTempl_); @@ -327,7 +347,11 @@ this.openVideoResSettings_(deviceId, videoRs, videoItem); } }); - this.resMenu_.appendChild(extItem); + if (index < focusIdx) { + this.resMenu_.insertBefore(extItem, fTitle); + } else { + this.resMenu_.appendChild(extItem); + } }); };
diff --git a/chrome/browser/resources/print_preview/data/destination_store.js b/chrome/browser/resources/print_preview/data/destination_store.js index 097a0cb8..8f72f8cd 100644 --- a/chrome/browser/resources/print_preview/data/destination_store.js +++ b/chrome/browser/resources/print_preview/data/destination_store.js
@@ -916,27 +916,27 @@ return true; } - return this.fetchPreselectedDestination_( - assert(recentDestinations.find(d => { - return print_preview.createRecentDestinationKey(d) === key; - }))); - } + const recent = recentDestinations.find(d => { + return print_preview.createRecentDestinationKey(d) === key; + }); + if (recent) { + return this.fetchPreselectedDestination_(recent); + } - /** Pre-fetches the Google Drive destination for the current active user. */ - startLoadDriveDestination() { + // Should be fetching the Google Drive destination. const driveKey = print_preview.createDestinationKey( print_preview.Destination.GooglePromotedId.DOCS, print_preview.DestinationOrigin.COOKIES, this.activeUser_); - if (!this.cloudPrintInterface_ || this.destinationMap_.get(driveKey) || - this.inFlightCloudPrintRequests_.has(driveKey)) { - // Already loaded or loading, or no cloud print interface. - return; - } - - this.inFlightCloudPrintRequests_.add(driveKey); - this.cloudPrintInterface_.printer( - print_preview.Destination.GooglePromotedId.DOCS, - print_preview.DestinationOrigin.COOKIES, this.activeUser_); + assert(key === driveKey); + return this.fetchPreselectedDestination_({ + id: print_preview.Destination.GooglePromotedId.DOCS, + origin: print_preview.DestinationOrigin.COOKIES, + account: this.activeUser_, + capabilities: null, + displayName: '', + extensionId: '', + extensionName: '', + }); } // <if expr="chromeos">
diff --git a/chrome/browser/resources/print_preview/data/user_info.js b/chrome/browser/resources/print_preview/data/user_info.js index f084409..de61c96 100644 --- a/chrome/browser/resources/print_preview/data/user_info.js +++ b/chrome/browser/resources/print_preview/data/user_info.js
@@ -59,16 +59,7 @@ this.tracker_.add( cloudPrintInterface.getEventTarget(), cloudprint.CloudPrintInterfaceEventType.UPDATE_USERS, - this.updateUsers_.bind(this)); - }, - - /** - * @param {string} user The new active user. - * @private - */ - setActiveUser_: function(user) { - this.destinationStore.setActiveUser(user); - this.activeUser = user; + this.onCloudPrintUpdateUsers_.bind(this)); }, /** @@ -76,16 +67,30 @@ * active user and users. * @private */ - updateUsers_: function(e) { - this.setActiveUser_(e.detail.activeUser); + onCloudPrintUpdateUsers_: function(e) { + this.updateActiveUser(e.detail.activeUser, false); if (e.detail.users) { - this.users = e.detail.users; + this.updateUsers(e.detail.users); } }, - /** @param {string} user The new active user. */ - updateActiveUser: function(user) { - this.setActiveUser_(user); + /** @param {!Array<string>} users The full list of signed in users. */ + updateUsers: function(users) { + this.users = users; + }, + + /** + * @param {string} user The new active user. + * @param {boolean} reloadCookies Whether to reload cookie based destinations + * and invitations. + */ + updateActiveUser: function(user, reloadCookies) { + this.destinationStore.setActiveUser(user); + this.activeUser = user; + if (!reloadCookies) { + return; + } + this.destinationStore.reloadUserCookieBasedDestinations(user); this.invitationStore.startLoadingInvitations(user); },
diff --git a/chrome/browser/resources/print_preview/ui/advanced_settings_item.html b/chrome/browser/resources/print_preview/ui/advanced_settings_item.html index 1f6fe09f..ee686cd 100644 --- a/chrome/browser/resources/print_preview/ui/advanced_settings_item.html +++ b/chrome/browser/resources/print_preview/ui/advanced_settings_item.html
@@ -24,7 +24,6 @@ overflow: hidden; text-overflow: ellipsis; vertical-align: middle; - white-space: nowrap; } .label, @@ -32,18 +31,20 @@ align-self: center; color: var(--cr-primary-text-color); overflow: hidden; - text-overflow: ellipsis; } .label { flex: 1; margin-inline-end: 10px; + min-width: 96px; opacity: 0.87; } .value { flex: 0; min-width: 239px; + text-overflow: ellipsis; + white-space: nowrap; } cr-input {
diff --git a/chrome/browser/resources/print_preview/ui/advanced_settings_item.js b/chrome/browser/resources/print_preview/ui/advanced_settings_item.js index 9011b96..4b01e0e 100644 --- a/chrome/browser/resources/print_preview/ui/advanced_settings_item.js +++ b/chrome/browser/resources/print_preview/ui/advanced_settings_item.js
@@ -11,11 +11,8 @@ /** @type {!print_preview.VendorCapability} */ capability: Object, - /** @private {(number | string | boolean)} */ - currentValue_: { - type: Object, - value: null, - }, + /** @private {string} */ + currentValue_: String, }, observers: [ @@ -76,9 +73,9 @@ * @private */ isOptionSelected_: function(option) { - return (this.currentValue_ !== null && - option.value === this.currentValue_) || - (this.currentValue_ == null && !!option.is_default); + return this.currentValue_ === undefined ? + !!option.is_default : + option.value === this.currentValue_; }, /** @@ -140,15 +137,16 @@ }, /** - * @return {(number | string | boolean)} The current value of the setting. + * @return {string} The current value of the setting, or the empty string if + * it is not set. */ getCurrentValue: function() { - return this.currentValue_; + return this.currentValue_ || ''; }, /** * Only used in tests. - * @param {(number | string | boolean)} value A value to set the setting to. + * @param {string} value A value to set the setting to. */ setCurrentValueForTest: function(value) { this.currentValue_ = value;
diff --git a/chrome/browser/resources/print_preview/ui/app.js b/chrome/browser/resources/print_preview/ui/app.js index 6758986..7c15940 100644 --- a/chrome/browser/resources/print_preview/ui/app.js +++ b/chrome/browser/resources/print_preview/ui/app.js
@@ -276,7 +276,8 @@ this.setSetting('selectionOnly', settings.shouldPrintSelectionOnly); this.$.sidebar.init( settings.isInAppKioskMode, settings.printerName, - settings.serializedDefaultDestinationSelectionRulesStr); + settings.serializedDefaultDestinationSelectionRulesStr, + settings.userAccounts || null); this.isInKioskAutoPrintMode_ = settings.isInKioskAutoPrintMode; // This is only visible in the task manager.
diff --git a/chrome/browser/resources/print_preview/ui/destination_settings.js b/chrome/browser/resources/print_preview/ui/destination_settings.js index 94343446..b7df87b 100644 --- a/chrome/browser/resources/print_preview/ui/destination_settings.js +++ b/chrome/browser/resources/print_preview/ui/destination_settings.js
@@ -182,9 +182,17 @@ * @param {string} defaultPrinter The system default printer ID. * @param {string} serializedDefaultDestinationRulesStr String with rules for * selecting a default destination. + * @param {?Array<string>} userAccounts The signed in user accounts. */ - initDestinationStore: function( - defaultPrinter, serializedDefaultDestinationRulesStr) { + init: function( + defaultPrinter, serializedDefaultDestinationRulesStr, userAccounts) { + if (!!userAccounts && userAccounts.length > 0) { + this.$.userInfo.updateActiveUser(userAccounts[0], false); + this.$.userInfo.updateUsers(userAccounts); + } else if (userAccounts) { + this.cloudPrintState_ = print_preview.CloudPrintState.NOT_SIGNED_IN; + } + this.destinationStore_.init( this.appKioskMode, defaultPrinter, serializedDefaultDestinationRulesStr, /** @type {!Array<print_preview.RecentDestination>} */ @@ -200,10 +208,6 @@ assert(this.cloudPrintState_ !== print_preview.CloudPrintState.DISABLED); this.cloudPrintState_ = print_preview.CloudPrintState.SIGNED_IN; - // Load docs, in case the user was not signed in previously and signed in - // from the destinations dialog. - this.destinationStore_.startLoadDriveDestination(); - if (this.destinationState === print_preview.DestinationState.SELECTED && this.destination.origin === print_preview.DestinationOrigin.COOKIES) { // Adjust states if the destination is now ready to be printed to. @@ -231,12 +235,6 @@ // destinationState. this.destination = destination; this.updateRecentDestinations_(); - if (this.cloudPrintState_ === print_preview.CloudPrintState.ENABLED) { - // Try to load the docs destination. This will trigger a response from - // the cloud print server that will tell Print Preview whether the user is - // signed in. - this.destinationStore_.startLoadDriveDestination(); - } }, /** @private */ @@ -439,7 +437,7 @@ * @private */ onAccountChange_: function(e) { - this.$.userInfo.updateActiveUser(e.detail); + this.$.userInfo.updateActiveUser(e.detail, true); }, /** @private */
diff --git a/chrome/browser/resources/print_preview/ui/pages_settings.js b/chrome/browser/resources/print_preview/ui/pages_settings.js index aa6193f..64f6d0a 100644 --- a/chrome/browser/resources/print_preview/ui/pages_settings.js +++ b/chrome/browser/resources/print_preview/ui/pages_settings.js
@@ -273,7 +273,7 @@ computeRangesToPrint_: function() { if (!this.pagesToPrint_ || this.pagesToPrint_.length == 0 || this.pagesToPrint_[0] == -1 || - this.pagesToPrint_ == this.allPagesArray_) { + this.pagesToPrint_.length == this.allPagesArray_.length) { return []; }
diff --git a/chrome/browser/resources/print_preview/ui/sidebar.js b/chrome/browser/resources/print_preview/ui/sidebar.js index 3a323be..8ac63482 100644 --- a/chrome/browser/resources/print_preview/ui/sidebar.js +++ b/chrome/browser/resources/print_preview/ui/sidebar.js
@@ -110,12 +110,14 @@ * @param {string} defaultPrinter The system default printer ID. * @param {string} serializedDestinationSelectionRulesStr String with rules * for selecting the default destination. + * @param {?Array<string>} userAccounts The signed in user accounts. */ init: function( - appKioskMode, defaultPrinter, serializedDestinationSelectionRulesStr) { + appKioskMode, defaultPrinter, serializedDestinationSelectionRulesStr, + userAccounts) { this.isInAppKioskMode_ = appKioskMode; - this.$.destinationSettings.initDestinationStore( - defaultPrinter, serializedDestinationSelectionRulesStr); + this.$.destinationSettings.init( + defaultPrinter, serializedDestinationSelectionRulesStr, userAccounts); }, /**
diff --git a/chrome/browser/resources/settings/os_settings_resources.grd b/chrome/browser/resources/settings/os_settings_resources.grd index eebda2c..d8021a7 100644 --- a/chrome/browser/resources/settings/os_settings_resources.grd +++ b/chrome/browser/resources/settings/os_settings_resources.grd
@@ -1232,13 +1232,8 @@ type="chrome_html"/> <structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_KERBEROS_ACCOUNTS_JS" file="people_page/kerberos_accounts.js" - type="chrome_html"/> - <structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_KERBEROS_ADD_ACCOUNT_DIALOG_HTML" - file="people_page/kerberos_add_account_dialog.html" - type="chrome_html"/> - <structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_KERBEROS_ADD_ACCOUNT_DIALOG_JS" - file="people_page/kerberos_add_account_dialog.js" - type="chrome_html"/> + type="chrome_html" + preprocess="true" /> <structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_KEREROS_ACCOUNTS_BROWSER_PROXY_HTML" file="people_page/kerberos_accounts_browser_proxy.html" type="chrome_html"/>
diff --git a/chrome/browser/resources/settings/people_page/BUILD.gn b/chrome/browser/resources/settings/people_page/BUILD.gn index 68f69699..6750eb3 100644 --- a/chrome/browser/resources/settings/people_page/BUILD.gn +++ b/chrome/browser/resources/settings/people_page/BUILD.gn
@@ -33,7 +33,6 @@ ":fingerprint_list", ":kerberos_accounts", ":kerberos_accounts_browser_proxy", - ":kerberos_add_account_dialog", ":lock_screen", ":lock_screen_password_prompt_dialog", ":lock_state_behavior", @@ -126,15 +125,6 @@ ] } -js_library("kerberos_add_account_dialog") { - deps = [ - ":kerberos_accounts_browser_proxy", - "//ui/webui/resources/cr_elements/cr_input:cr_input", - "//ui/webui/resources/js:cr", - "//ui/webui/resources/js:i18n_behavior", - "//ui/webui/resources/js:web_ui_listener_behavior", - ] -} js_library("lock_screen") { deps = [ ":fingerprint_browser_proxy",
diff --git a/chrome/browser/resources/settings/people_page/kerberos_accounts.html b/chrome/browser/resources/settings/people_page/kerberos_accounts.html index b7b295f..b977bbc 100644 --- a/chrome/browser/resources/settings/people_page/kerberos_accounts.html +++ b/chrome/browser/resources/settings/people_page/kerberos_accounts.html
@@ -11,7 +11,6 @@ <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="../settings_shared_css.html"> <link rel="import" href="kerberos_accounts_browser_proxy.html"> -<link rel="import" href="kerberos_add_account_dialog.html"> <dom-module id="settings-kerberos-accounts"> <template> @@ -64,7 +63,7 @@ <div id="account-list-header" class="flex"> <h2>$i18n{kerberosAccountsListHeader}</h2> </div> - <paper-button id="add-account-button" on-click="onAddAccountClick_"> + <paper-button id="add-account-button" on-click="addAccount_"> <div id="add-account-icon"></div> $i18n{kerberosAccountsAddAccountLabel} </paper-button> @@ -113,12 +112,6 @@ </button> </cr-action-menu> </div> - - <template is="dom-if" if="[[showAddAccountDialog_]]" restamp> - <kerberos-add-account-dialog username="[[addAccountPresetUsername_]]" - on-close="onAddAccountDialogClosed_"> - </kerberos-add-account-dialog> - </template> </template> <script src="kerberos_accounts.js"></script> </dom-module> \ No newline at end of file
diff --git a/chrome/browser/resources/settings/people_page/kerberos_accounts.js b/chrome/browser/resources/settings/people_page/kerberos_accounts.js index 219fe4f..cf85a05 100644 --- a/chrome/browser/resources/settings/people_page/kerberos_accounts.js +++ b/chrome/browser/resources/settings/people_page/kerberos_accounts.js
@@ -32,15 +32,6 @@ * @private {?settings.KerberosAccount} */ actionMenuAccount_: Object, - - /** @private */ - addAccountPresetUsername_: { - type: String, - value: '', - }, - - /** @private */ - showAddAccountDialog_: Boolean, }, /** @private {?settings.KerberosAccountsBrowserProxy} */ @@ -72,9 +63,8 @@ * @param {!Event} event * @private */ - onAddAccountClick_: function(event) { - this.addAccountPresetUsername_ = ''; - this.showAddAccountDialog_ = true; + addAccount_: function(event) { + this.browserProxy_.addAccount(); }, /** @@ -82,13 +72,7 @@ * @private */ onReauthenticationClick_: function(event) { - this.addAccountPresetUsername_ = event.model.item.principalName; - this.showAddAccountDialog_ = true; - }, - - /** @private */ - onAddAccountDialogClosed_: function() { - this.showAddAccountDialog_ = false; + this.browserProxy_.reauthenticateAccount(event.model.item.principalName); }, /**
diff --git a/chrome/browser/resources/settings/people_page/kerberos_accounts_browser_proxy.html b/chrome/browser/resources/settings/people_page/kerberos_accounts_browser_proxy.html index c74b570..7ca5511cc 100644 --- a/chrome/browser/resources/settings/people_page/kerberos_accounts_browser_proxy.html +++ b/chrome/browser/resources/settings/people_page/kerberos_accounts_browser_proxy.html
@@ -1,2 +1 @@ -<link rel="import" href="chrome://resources/html/cr.html"> <script src="kerberos_accounts_browser_proxy.js"></script> \ No newline at end of file
diff --git a/chrome/browser/resources/settings/people_page/kerberos_accounts_browser_proxy.js b/chrome/browser/resources/settings/people_page/kerberos_accounts_browser_proxy.js index 25ec4f1..a9731c7 100644 --- a/chrome/browser/resources/settings/people_page/kerberos_accounts_browser_proxy.js +++ b/chrome/browser/resources/settings/people_page/kerberos_accounts_browser_proxy.js
@@ -20,33 +20,6 @@ settings.KerberosAccount; cr.define('settings', function() { - /** - * @enum {number} - * These values must be kept in sync with the ErrorType enum in - * third_party/cros_system_api/dbus/kerberos/kerberos_service.proto. - */ - const KerberosErrorType = { - kNone: 0, - kUnknown: 1, - kDBusFailure: 2, - kNetworkProblem: 3, - kUnknownKrb5Error: 4, - kBadPrincipal: 5, - kBadPassword: 6, - kPasswordExpired: 7, - kPasswordRejected: 8, - kNoCredentialsCacheFound: 9, - kKerberosTicketExpired: 10, - kKdcDoesNotSupportEncryptionType: 11, - kContactingKdcFailed: 12, - kParseRequestFailed: 13, - kLocalIo: 14, - kUnknownPrincipalName: 15, - kDuplicatePrincipalName: 16, - kInProgress: 17, - kParsePrincipalFailed: 18, - }; - /** @interface */ class KerberosAccountsBrowserProxy { /** @@ -57,12 +30,16 @@ getAccounts() {} /** - * Attempts to add a new (or update an existing) Kerberos account. - * @param {string} principalName Kerberos principal (user@realm.com). - * @param {string} password Account password. - * @return {!Promise<!settings.KerberosErrorType>} + * Triggers the 'Add account' flow. */ - addAccount(principalName, password) {} + addAccount() {} + + /** + * Triggers the re-authentication flow for the account pointed to by + * |principalName|. + * @param {!string} principalName + */ + reauthenticateAccount(principalName) {} /** * Removes |account| from the set of Kerberos accounts. @@ -81,8 +58,13 @@ } /** @override */ - addAccount(principalName, password) { - return cr.sendWithPromise('addKerberosAccount', principalName, password); + addAccount() { + chrome.send('addKerberosAccount'); + } + + /** @override */ + reauthenticateAccount(principalName) { + chrome.send('reauthenticateKerberosAccount', [principalName]); } /** @override */ @@ -94,7 +76,6 @@ cr.addSingletonGetter(KerberosAccountsBrowserProxyImpl); return { - KerberosErrorType: KerberosErrorType, KerberosAccountsBrowserProxy: KerberosAccountsBrowserProxy, KerberosAccountsBrowserProxyImpl: KerberosAccountsBrowserProxyImpl, };
diff --git a/chrome/browser/resources/settings/people_page/kerberos_add_account_dialog.html b/chrome/browser/resources/settings/people_page/kerberos_add_account_dialog.html deleted file mode 100644 index c6a15532..0000000 --- a/chrome/browser/resources/settings/people_page/kerberos_add_account_dialog.html +++ /dev/null
@@ -1,63 +0,0 @@ -<link rel="import" href="chrome://resources/html/polymer.html"> - -<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> -<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html"> -<link rel="import" href="chrome://resources/cr_elements/icons.html"> -<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> -<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> -<link rel="import" href="chrome://resources/html/i18n_behavior.html"> -<link rel="import" href="chrome://resources/html/load_time_data.html"> -<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> -<link rel="import" href="kerberos_accounts_browser_proxy.html"> - -<dom-module id="kerberos-add-account-dialog"> - <template> - <style include="paper-button-style"> - .label { - @apply --cr-form-field-label; - } - - #credentials > cr-input:not(:last-child) { - margin-bottom: var(--cr-form-field-bottom-spacing); - } - - #general-error-container { - height: 48px; - } - </style> - <cr-dialog id="dialog"> - <div slot="title">$i18n{addKerberosAccount}</div> - <div slot="body" spellcheck="false"> - <div id="general-error-container"> - <div hidden="[[!showError_(generalErrorText_)]]"> - <iron-icon id="general-error-icon" icon="cr:warning"></iron-icon> - <div id="general-error-message">[[generalErrorText_]]</div> - </div> - </div> - <div id="credentials"> - <cr-input id="username" label="$i18n{kerberosUsername}" - value="{{username}}" invalid="[[showError_(usernameErrorText_)]]" - error-message="[[usernameErrorText_]]"> - </cr-input> - <cr-input id="password" type="password" - label="$i18n{kerberosPassword}" value="{{password_}}" - invalid="[[showError_(passwordErrorText_)]]" - error-message="[[passwordErrorText_]]"> - </cr-input> - </div> - </div> - <div slot="button-container"> - <paper-button class="cancel-button" on-click="onCancel_" id="cancel"> - $i18n{cancel} - </paper-button> - <paper-button class="action-button" on-click="onAdd_" - disabled="[[inProgress_]]"> - $i18n{add} - </paper-button> - </div> - </cr-dialog> - </template> - <script src="kerberos_add_account_dialog.js"></script> -</dom-module> \ No newline at end of file
diff --git a/chrome/browser/resources/settings/people_page/kerberos_add_account_dialog.js b/chrome/browser/resources/settings/people_page/kerberos_add_account_dialog.js deleted file mode 100644 index 2b139099..0000000 --- a/chrome/browser/resources/settings/people_page/kerberos_add_account_dialog.js +++ /dev/null
@@ -1,151 +0,0 @@ -// Copyright 2019 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. - -/** - * @fileoverview - * 'kerberos-add-account-dialog' is an element to add Kerberos accounts. - */ - -Polymer({ - is: 'kerberos-add-account-dialog', - - behaviors: [I18nBehavior], - - properties: { - username: { - type: String, - value: '', - }, - - /** @private */ - password_: { - type: String, - value: '', - }, - - /** @private */ - generalErrorText_: { - type: String, - value: '', - }, - - /** @private */ - usernameErrorText_: { - type: String, - value: '', - }, - - /** @private */ - passwordErrorText_: { - type: String, - value: '', - }, - - /** @private */ - inProgress_: { - type: Boolean, - value: false, - }, - }, - - /** @private {?settings.KerberosAccountsBrowserProxy} */ - browserProxy_: null, - - /** @private {!settings.KerberosErrorType} */ - lastError_: settings.KerberosErrorType.kNone, - - /** @override */ - attached: function() { - this.$.dialog.showModal(); - - // If a non-empty username is preset, make the UI read-only. - // Note: At least the focus() part needs to be after showModal. - if (this.username) { - this.$.username.disabled = true; - this.$.password.focus(); - } - }, - - /** @private */ - onCancel_: function() { - this.$.dialog.cancel(); - }, - - /** @private */ - onAdd_: function() { - this.inProgress_ = true; - this.updateErrorMessages_(settings.KerberosErrorType.kNone); - - settings.KerberosAccountsBrowserProxyImpl.getInstance() - .addAccount(this.username, this.password_) - .then(error => { - this.inProgress_ = false; - - // Success case. Close dialog. - if (error == settings.KerberosErrorType.kNone) { - this.$.dialog.close(); - return; - } - - // Triggers the UI to update error messages. - this.updateErrorMessages_(error); - }); - }, - - /** - * @param {!settings.KerberosErrorType} error Current error enum - * @private - */ - updateErrorMessages_: function(error) { - this.lastError_ = error; - - this.generalErrorText_ = ''; - this.usernameErrorText_ = ''; - this.passwordErrorText_ = ''; - - switch (error) { - // TODO(ljusten): Proper errors - case settings.KerberosErrorType.kNone: - break; - - case settings.KerberosErrorType.kNetworkProblem: - this.generalErrorText_ = 'Network problem or bad realm'; - break; - case settings.KerberosErrorType.kParsePrincipalFailed: - this.usernameErrorText_ = 'Username invalid (should be user@realm.com)'; - break; - case settings.KerberosErrorType.kBadPrincipal: - this.usernameErrorText_ = 'Username not known to server'; - break; - case settings.KerberosErrorType.kContactingKdcFailed: - this.usernameErrorText_ = 'Contacting server for realm failed'; - break; - - case settings.KerberosErrorType.kBadPassword: - this.passwordErrorText_ = 'Password invalid'; - break; - case settings.KerberosErrorType.kPasswordExpired: - this.passwordErrorText_ = 'Password expired'; - break; - - case settings.KerberosErrorType.kKdcDoesNotSupportEncryptionType: - this.generalErrorText_ = 'KDC does not support encryption type'; - break; - default: - this.generalErrorText_ = this.i18nDynamic( - this.locale, 'kerberosGeneralErrorMessage', String(error)); - } - }, - - /** - * Whether an error element should be shown. - * Note that !! is not supported in Polymer bindings. - * @param {?string} errorText Error text to be displayed. Empty if no error. - * @return {boolean} True iff errorText is not empty. - * @private - */ - showError_: function(errorText) { - return !!errorText; - } -}); \ No newline at end of file
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html index 1f20da28..af3d2d2f9 100644 --- a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html +++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html
@@ -187,13 +187,15 @@ </a> </div> <div class="settings-box two-line"> - <cr-searchable-drop-down items="[[manufacturerList]]" + <cr-searchable-drop-down id="manufacturerDropdown" + items="[[manufacturerList]]" label="$i18n{printerManufacturer}" value="{{activePrinter.ppdManufacturer}}"> </cr-searchable-drop-down> </div> <div class="settings-box two-line"> - <cr-searchable-drop-down items="[[modelList]]" + <cr-searchable-drop-down id="modelDropdown" + items="[[modelList]]" label="$i18n{printerModel}" value="{{activePrinter.ppdModel}}"> </cr-searchable-drop-down> @@ -207,6 +209,9 @@ $i18n{selectDriverButtonText} </paper-button> </div> + <div class="eula" id="eulaUrl" hidden="[[!eulaUrl_]]"> + <a href="[[eulaUrl_]]" target="_blank">$i18n{printerEulaNotice}</a> + </div> </div> <div slot="dialog-buttons"> <paper-button class="cancel-button secondary-button"
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js index 80ca448..37fe0cc 100644 --- a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js +++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js
@@ -235,10 +235,20 @@ * @private */ newUserPPD_: String, + + /** + * The URL to a printer's EULA. + * @private + */ + eulaUrl_: { + type: String, + value: '', + }, }, observers: [ 'selectedManufacturerChanged_(activePrinter.ppdManufacturer)', + 'selectedModelChanged_(activePrinter.ppdModel)', ], /** @override */ @@ -280,6 +290,32 @@ }, /** + * Attempts to get the EULA Url if the selected printer has one. + * @private + */ + selectedModelChanged_: function() { + if (!this.activePrinter.ppdManufacturer || !this.activePrinter.ppdModel) { + // Do not check for an EULA unless both |ppdManufacturer| and |ppdModel| + // are set. Set |eulaUrl_| to be empty in this case. + this.onGetEulaUrlCompleted_('' /* eulaUrl */); + return; + } + + settings.CupsPrintersBrowserProxyImpl.getInstance() + .getEulaUrl( + this.activePrinter.ppdManufacturer, this.activePrinter.ppdModel) + .then(this.onGetEulaUrlCompleted_.bind(this)); + }, + + /** + * @param {string} eulaUrl The URL for the printer's EULA. + * @private + */ + onGetEulaUrlCompleted_: function(eulaUrl) { + this.eulaUrl_ = eulaUrl; + }, + + /** * @param {!ManufacturersInfo} manufacturersInfo * @private */ @@ -521,7 +557,7 @@ this.newPrinter.printerId); } else if (this.previousDialog_ == AddPrinterDialogs.MANUFACTURER) { this.configuringDialogTitle = - loadTimeData.getString('selectManufacturerAndModelTitle'); + loadTimeData.getString('manufacturerAndModelDialogTitle'); this.addPrinter_(); } else if (this.previousDialog_ == AddPrinterDialogs.MANUALLY) { this.configuringDialogTitle =
diff --git a/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html b/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html index e1e85f9..7acadc0c 100644 --- a/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html +++ b/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html
@@ -4,6 +4,7 @@ <link rel="import" href="chrome://resources/cr_elements/cr_scrollable_behavior.html"> <link rel="import" href="chrome://resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> +<link rel="import" href="../i18n_setup.html"> <link rel="import" href="cups_add_printer_dialog_elements.html"> <link rel="import" href="cups_printer_dialog_util.html"> <link rel="import" href="cups_printer_shared_css.html"> @@ -106,6 +107,9 @@ $i18n{selectDriverButtonText} </paper-button> </div> + <div class="eula" id="eulaUrl" hidden="[[!eulaUrl_]]"> + <a href="[[eulaUrl_]]" target="_blank">$i18n{printerEulaNotice}</a> + </div> </div> <div slot="dialog-buttons"> <paper-button class="cancel-button secondary-button"
diff --git a/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js b/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js index cb0d4a22..2e5404f 100644 --- a/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js +++ b/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js
@@ -92,6 +92,15 @@ * @private */ newUserPPD_: String, + + /** + * The URL to a printer's EULA. + * @private + */ + eulaUrl_: { + type: String, + value: '', + }, }, observers: [ @@ -235,13 +244,35 @@ }, /** - * Sets printerInfoChanged_ to true to show that the model has changed. + * Sets printerInfoChanged_ to true to show that the model has changed. Also + * attempts to get the EULA Url if the selected printer has one. * @private */ onModelChanged_: function() { if (this.arePrinterFieldsInitialized_) { this.printerInfoChanged_ = true; } + + if (!this.pendingPrinter_.ppdManufacturer || + !this.pendingPrinter_.ppdModel) { + // Do not check for an EULA unless both |ppdManufacturer| and |ppdModel| + // are set. Set |eulaUrl_| to be empty in this case. + this.onGetEulaUrlCompleted_('' /* eulaUrl */); + return; + } + + settings.CupsPrintersBrowserProxyImpl.getInstance() + .getEulaUrl( + this.pendingPrinter_.ppdManufacturer, this.pendingPrinter_.ppdModel) + .then(this.onGetEulaUrlCompleted_.bind(this)); + }, + + /** + * @param {string} eulaUrl The URL for the printer's EULA. + * @private + */ + onGetEulaUrlCompleted_: function(eulaUrl) { + this.eulaUrl_ = eulaUrl; }, /** @private */
diff --git a/chrome/browser/resources/settings/printing_page/cups_printer_shared_css.html b/chrome/browser/resources/settings/printing_page/cups_printer_shared_css.html index 5a21b6c..a8040ee 100644 --- a/chrome/browser/resources/settings/printing_page/cups_printer_shared_css.html +++ b/chrome/browser/resources/settings/printing_page/cups_printer_shared_css.html
@@ -62,6 +62,10 @@ width: 100%; } + [slot='dialog-body'] .eula { + padding-inline-start: 20px; + } + [slot='dialog-buttons'] { display: flex; justify-content: space-between;
diff --git a/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js b/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js index d083e82..b309666 100644 --- a/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js +++ b/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js
@@ -180,6 +180,14 @@ * @param {!CupsPrinterInfo} newPrinter */ cancelPrinterSetUp(newPrinter) {} + + /** + * @param {string} ppdManufacturer + * @param {string} ppdModel + * @return {!Promise<string>} Returns the EULA URL of the printer. Returns + * an empty string if no EULA is required. + */ + getEulaUrl(ppdManufacturer, ppdModel) {} } /** @@ -255,6 +263,11 @@ cancelPrinterSetUp(newPrinter) { chrome.send('cancelPrinterSetUp', [newPrinter]); } + + /** @override */ + getEulaUrl(ppdManufacturer, ppdModel) { + return cr.sendWithPromise('getEulaUrl', ppdManufacturer, ppdModel); + } } cr.addSingletonGetter(CupsPrintersBrowserProxyImpl);
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd index 4b220cb..50e2709 100644 --- a/chrome/browser/resources/settings/settings_resources.grd +++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -1519,12 +1519,6 @@ <structure name="IDR_SETTINGS_PEOPLE_PAGE_KERBEROS_ACCOUNTS_JS" file="people_page/kerberos_accounts.js" type="chrome_html"/> - <structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_KERBEROS_ADD_ACCOUNT_DIALOG_HTML" - file="people_page/kerberos_add_account_dialog.html" - type="chrome_html"/> - <structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_KERBEROS_ADD_ACCOUNT_DIALOG_JS" - file="people_page/kerberos_add_account_dialog.js" - type="chrome_html"/> <structure name="IDR_SETTINGS_PEOPLE_PAGE_KERBEROS_ACCOUNTS_BROWSER_PROXY_HTML" file="people_page/kerberos_accounts_browser_proxy.html" type="chrome_html"/>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html index dba91a4..6e53f1b 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html +++ b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html
@@ -170,6 +170,12 @@ url(chrome://welcome/images/news_2x.png) 2x); } + .search { + content: -webkit-image-set( + url(chrome://theme/IDS_ONBOARDING_WELCOME_SEARCH@1x) 1x, + url(chrome://theme/IDS_ONBOARDING_WELCOME_SEARCH@2x) 2x); + } + .web-store { content: -webkit-image-set( url(chrome://welcome/images/chrome_store_1x.png) 1x,
diff --git a/chrome/browser/search/background/ntp_background_service.cc b/chrome/browser/search/background/ntp_background_service.cc index 6cefbba..8124da2 100644 --- a/chrome/browser/search/background/ntp_background_service.cc +++ b/chrome/browser/search/background/ntp_background_service.cc
@@ -267,6 +267,23 @@ collection_images_.push_back(image); } +void NtpBackgroundService::AddValidBackdropUrlWithThumbnailForTesting( + const GURL& url, + const GURL& thumbnail_url) { + CollectionImage image; + image.image_url = url; + image.thumbnail_image_url = thumbnail_url; + collection_images_.push_back(image); +} + +const GURL& NtpBackgroundService::GetThumbnailUrl(const GURL& image_url) { + for (auto& image : collection_images_) { + if (image.image_url == image_url) + return image.thumbnail_image_url; + } + return GURL::EmptyGURL(); +} + void NtpBackgroundService::NotifyObservers(FetchComplete fetch_complete) { for (auto& observer : observers_) { switch (fetch_complete) {
diff --git a/chrome/browser/search/background/ntp_background_service.h b/chrome/browser/search/background/ntp_background_service.h index de41780..64a7163 100644 --- a/chrome/browser/search/background/ntp_background_service.h +++ b/chrome/browser/search/background/ntp_background_service.h
@@ -55,6 +55,13 @@ void AddValidBackdropUrlForTesting(const GURL& url); + void AddValidBackdropUrlWithThumbnailForTesting(const GURL& url, + const GURL& thumbnail_url); + + // Returns thumbnail url for the given image url if its valid. Otherwise, + // returns empty url. + const GURL& GetThumbnailUrl(const GURL& image_url); + // Returns the currently cached CollectionInfo, if any. const std::vector<CollectionInfo>& collection_info() const { return collection_info_;
diff --git a/chrome/browser/search/background/ntp_background_service_unittest.cc b/chrome/browser/search/background/ntp_background_service_unittest.cc index e7d5a73..5d04323 100644 --- a/chrome/browser/search/background/ntp_background_service_unittest.cc +++ b/chrome/browser/search/background/ntp_background_service_unittest.cc
@@ -261,3 +261,14 @@ EXPECT_FALSE(service()->IsValidBackdropUrl( GURL("https://wallpapers.co/another_image"))); } + +TEST_F(NtpBackgroundServiceTest, GetThumbnailUrl) { + const GURL kInvalidUrl("foo"); + const GURL kValidUrl("https://www.foo.com"); + const GURL kValidThumbnailUrl("https://www.foo.com/thumbnail"); + service()->AddValidBackdropUrlWithThumbnailForTesting(kValidUrl, + kValidThumbnailUrl); + + EXPECT_EQ(kValidThumbnailUrl, service()->GetThumbnailUrl(kValidUrl)); + EXPECT_EQ(GURL::EmptyGURL(), service()->GetThumbnailUrl(kInvalidUrl)); +}
diff --git a/chrome/browser/search/instant_service.cc b/chrome/browser/search/instant_service.cc index 449a5bb..12f07f9 100644 --- a/chrome/browser/search/instant_service.cc +++ b/chrome/browser/search/instant_service.cc
@@ -17,6 +17,7 @@ #include "base/task/post_task.h" #include "build/build_config.h" #include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/image_fetcher/image_decoder_impl.h" #include "chrome/browser/ntp_tiles/chrome_most_visited_sites_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search/background/ntp_background_service.h" @@ -51,7 +52,9 @@ #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" #include "content/public/browser/render_process_host.h" +#include "content/public/browser/storage_partition.h" #include "content/public/browser/url_data_source.h" +#include "ui/gfx/color_analysis.h" #include "ui/gfx/color_utils.h" #include "ui/native_theme/dark_mode_observer.h" @@ -63,6 +66,8 @@ const char kNtpCustomBackgroundAttributionActionURL[] = "attribution_action_url"; +const char kImageFetcherUmaClientName[] = "NtpCustomBackgrounds"; + base::DictionaryValue GetBackgroundInfoAsDict( const GURL& background_url, const std::string& attribution_line_1, @@ -81,6 +86,33 @@ return background_info; } +// |GetBackgroundInfoWithColor| has to return new object so that updated version +// gets synced. +base::DictionaryValue GetBackgroundInfoWithColor( + const base::DictionaryValue* background_info, + const SkColor color) { + base::DictionaryValue new_background_info; + auto url = const_cast<base::Value&&>( + *background_info->FindKey(kNtpCustomBackgroundURL)); + auto attribution_line_1 = const_cast<base::Value&&>( + *background_info->FindKey(kNtpCustomBackgroundAttributionLine1)); + auto attribution_line_2 = const_cast<base::Value&&>( + *background_info->FindKey(kNtpCustomBackgroundAttributionLine2)); + auto action_url = const_cast<base::Value&&>( + *background_info->FindKey(kNtpCustomBackgroundAttributionActionURL)); + + new_background_info.SetKey(kNtpCustomBackgroundURL, url.Clone()); + new_background_info.SetKey(kNtpCustomBackgroundAttributionLine1, + attribution_line_1.Clone()); + new_background_info.SetKey(kNtpCustomBackgroundAttributionLine2, + attribution_line_2.Clone()); + new_background_info.SetKey(kNtpCustomBackgroundAttributionActionURL, + action_url.Clone()); + new_background_info.SetKey(kNtpCustomBackgroundMainColor, + base::Value((int)color)); + return new_background_info; +} + base::Value NtpCustomBackgroundDefaults() { base::Value defaults(base::Value::Type::DICTIONARY); defaults.SetKey(kNtpCustomBackgroundURL, @@ -113,8 +145,17 @@ std::move(*callback).Run(result); } +// |GetBitmapMainColor| just wraps |CalculateKMeanColorOfBitmap|. +// As |CalculateKMeanColorOfBitmap| is overloaded, it cannot be bind for async +// call. +SkColor GetBitmapMainColor(const SkBitmap& bitmap) { + return color_utils::CalculateKMeanColorOfBitmap(bitmap); +} + } // namespace +const char kNtpCustomBackgroundMainColor[] = "background_main_color"; + // Keeps track of any changes in search engine provider and notifies // InstantService if a third-party search provider (i.e. a third-party NTP) is // being used. @@ -231,6 +272,11 @@ prefs::kNtpCustomBackgroundDict, base::BindRepeating(&InstantService::UpdateBackgroundFromSync, weak_ptr_factory_.GetWeakPtr())); + + image_fetcher_ = std::make_unique<image_fetcher::ImageFetcherImpl>( + std::make_unique<ImageDecoderImpl>(), + content::BrowserContext::GetDefaultStoragePartition(profile_) + ->GetURLLoaderFactoryForBrowserProcess()); } InstantService::~InstantService() = default; @@ -383,6 +429,12 @@ RemoveLocalBackgroundImageCopy(); if (background_url.is_valid() && is_backdrop_url) { + const GURL& thumbnail_url = + background_service_->GetThumbnailUrl(background_url); + FetchCustomBackground(background_url, thumbnail_url.is_valid() + ? thumbnail_url + : background_url); + base::DictionaryValue background_info = GetBackgroundInfoAsDict( background_url, attribution_line_1, attribution_line_2, action_url); pref_service_->Set(prefs::kNtpCustomBackgroundDict, background_info); @@ -723,6 +775,52 @@ ResetCustomBackgroundThemeInfo(); } +void InstantService::UpdateCustomBackgroundColorAsync( + const GURL& image_url, + const gfx::Image& fetched_image, + const image_fetcher::RequestMetadata& metadata) { + // Calculate the bitmap color asynchronously as it is slow (1-2 seconds for + // the thumbnail). However, prefs should be updated on the main thread. + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, {base::TaskPriority::BEST_EFFORT}, + base::BindOnce(&GetBitmapMainColor, *fetched_image.ToSkBitmap()), + base::BindOnce(&InstantService::UpdateCustomBackgroundPrefsWithColor, + weak_ptr_factory_.GetWeakPtr(), image_url)); +} + +void InstantService::FetchCustomBackground(const GURL& image_url, + const GURL& fetch_url) { + DCHECK(!fetch_url.is_empty()); + + net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation("ntp_custom_background", + R"( + semantics { + sender: "Desktop Chrome background fetcher" + description: + "Fetch New Tab Page custom background for color calculation." + trigger: + "User selects new background on the New Tab Page." + data: "The only data sent is the path to an image" + destination: GOOGLE_OWNED_SERVICE + } + policy { + cookies_allowed: NO + setting: + "Users cannot disable this feature. The feature is enabled by " + "default." + policy_exception_justification: "Not implemented." + })"); + + image_fetcher::ImageFetcherParams params(traffic_annotation, + kImageFetcherUmaClientName); + image_fetcher_->FetchImage( + image_url, + base::BindOnce(&InstantService::UpdateCustomBackgroundColorAsync, + weak_ptr_factory_.GetWeakPtr(), image_url), + std::move(params)); +} + bool InstantService::IsCustomBackgroundPrefValid(GURL& custom_background_url) { const base::DictionaryValue* background_info = profile_->GetPrefs()->GetDictionary(prefs::kNtpCustomBackgroundDict); @@ -777,3 +875,24 @@ false); registry->RegisterBooleanPref(prefs::kNtpUseMostVisitedTiles, false); } + +void InstantService::UpdateCustomBackgroundPrefsWithColor(const GURL& image_url, + SkColor color) { + // Update background color only if the selected background is still the same. + const base::DictionaryValue* background_info = + pref_service_->GetDictionary(prefs::kNtpCustomBackgroundDict); + if (!background_info) + return; + + GURL current_bg_url( + background_info->FindKey(kNtpCustomBackgroundURL)->GetString()); + if (current_bg_url == image_url) { + pref_service_->Set(prefs::kNtpCustomBackgroundDict, + GetBackgroundInfoWithColor(background_info, color)); + } +} + +void InstantService::SetImageFetcherForTesting( + image_fetcher::ImageFetcher* image_fetcher) { + image_fetcher_ = base::WrapUnique(image_fetcher); +}
diff --git a/chrome/browser/search/instant_service.h b/chrome/browser/search/instant_service.h index 319bab81..c40e247e 100644 --- a/chrome/browser/search/instant_service.h +++ b/chrome/browser/search/instant_service.h
@@ -18,6 +18,7 @@ #include "base/optional.h" #include "build/build_config.h" #include "components/history/core/browser/history_types.h" +#include "components/image_fetcher/core/image_fetcher_impl.h" #include "components/keyed_service/core/keyed_service.h" #include "components/ntp_tiles/most_visited_sites.h" #include "components/ntp_tiles/ntp_tile.h" @@ -47,6 +48,8 @@ class DarkModeObserver; } // namespace ui +extern const char kNtpCustomBackgroundMainColor[]; + // Tracks render process host IDs that are associated with Instant, i.e. // processes that are used to render an NTP. Also responsible for keeping // necessary information (most visited tiles and theme info) updated in those @@ -154,11 +157,22 @@ // tests. virtual void ResetToDefault(); + // Calculates the most frequent color of the image and stores it in prefs. + void UpdateCustomBackgroundColorAsync( + const GURL& image_url, + const gfx::Image& fetched_image, + const image_fetcher::RequestMetadata& metadata); + + // Fetches the image for the given |fetch_url|. + void FetchCustomBackground(const GURL& image_url, const GURL& fetch_url); + private: class SearchProviderObserver; friend class InstantExtendedTest; friend class InstantUnitTestBase; + friend class LocalNTPBackgroundsAndDarkModeTest; + friend class TestInstantService; FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, ProcessIsolation); FRIEND_TEST_ALL_PREFIXES(InstantServiceTest, DeleteThumbnailDataIfExists); @@ -229,6 +243,12 @@ void CreateDarkModeObserver(ui::NativeTheme* theme); + // Updates custom background prefs with color for the given |image_url|. + void UpdateCustomBackgroundPrefsWithColor(const GURL& image_url, + SkColor color); + + void SetImageFetcherForTesting(image_fetcher::ImageFetcher* image_fetcher); + Profile* const profile_; // The process ids associated with Instant processes. @@ -261,6 +281,8 @@ NtpBackgroundService* background_service_; + std::unique_ptr<image_fetcher::ImageFetcher> image_fetcher_; + base::WeakPtrFactory<InstantService> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(InstantService);
diff --git a/chrome/browser/search/instant_service_unittest.cc b/chrome/browser/search/instant_service_unittest.cc index 2e09ed57..b2dfc78 100644 --- a/chrome/browser/search/instant_service_unittest.cc +++ b/chrome/browser/search/instant_service_unittest.cc
@@ -55,6 +55,18 @@ MOCK_METHOD0(ResetCustomBackgroundThemeInfo, void()); }; +bool CheckBackgroundColor(SkColor color, + const base::DictionaryValue* background_info) { + if (!background_info) + return false; + + const base::Value* background_color = + background_info->FindKey(kNtpCustomBackgroundMainColor); + if (!background_color) + return false; + + return color == static_cast<uint32_t>(background_color->GetInt()); +} } // namespace using InstantServiceTest = InstantUnitTestBase; @@ -576,3 +588,48 @@ EXPECT_EQ(std::string(), theme_info->custom_background_attribution_line_2); EXPECT_EQ(GURL(), theme_info->custom_background_attribution_action_url); } + +TEST_F(InstantServiceTest, TestUpdateCustomBackgroundColor) { + SkBitmap bitmap; + bitmap.allocN32Pixels(32, 32); + bitmap.eraseColor(SK_ColorRED); + gfx::Image image = gfx::Image::CreateFrom1xBitmap(bitmap); + sync_preferences::TestingPrefServiceSyncable* pref_service = + profile()->GetTestingPrefService(); + + ASSERT_FALSE(instant_service_->IsCustomBackgroundSet()); + + // Background color will not update if no background is set. + instant_service_->UpdateCustomBackgroundColorAsync( + GURL(), image, image_fetcher::RequestMetadata()); + thread_bundle()->RunUntilIdle(); + EXPECT_FALSE(CheckBackgroundColor( + SK_ColorRED, + pref_service->GetDictionary(prefs::kNtpCustomBackgroundDict))); + + const GURL kUrl("https://www.foo.com"); + const std::string kAttributionLine1 = "foo"; + const std::string kAttributionLine2 = "bar"; + const GURL kActionUrl("https://www.bar.com"); + + SetUserSelectedDefaultSearchProvider("{google:baseURL}"); + instant_service_->AddValidBackdropUrlForTesting(kUrl); + instant_service_->SetCustomBackgroundURLWithAttributions( + kUrl, kAttributionLine1, kAttributionLine2, kActionUrl); + + // Background color will not update if current background url changed. + instant_service_->UpdateCustomBackgroundColorAsync( + GURL("different_url"), image, image_fetcher::RequestMetadata()); + thread_bundle()->RunUntilIdle(); + EXPECT_FALSE(CheckBackgroundColor( + SK_ColorRED, + pref_service->GetDictionary(prefs::kNtpCustomBackgroundDict))); + + // Background color should update. + instant_service_->UpdateCustomBackgroundColorAsync( + kUrl, image, image_fetcher::RequestMetadata()); + thread_bundle()->RunUntilIdle(); + EXPECT_TRUE(CheckBackgroundColor( + SK_ColorRED, + pref_service->GetDictionary(prefs::kNtpCustomBackgroundDict))); +}
diff --git a/chrome/browser/search/instant_unittest_base.cc b/chrome/browser/search/instant_unittest_base.cc index 9c2df763..69f1e02 100644 --- a/chrome/browser/search/instant_unittest_base.cc +++ b/chrome/browser/search/instant_unittest_base.cc
@@ -20,6 +20,7 @@ #include "chrome/test/base/search_test_utils.h" #include "components/google/core/browser/google_pref_names.h" #include "components/google/core/browser/google_url_tracker.h" +#include "components/image_fetcher/core/mock_image_fetcher.h" #include "components/search/search.h" #include "components/search_engines/template_url.h" #include "components/search_engines/template_url_service.h" @@ -42,6 +43,9 @@ UIThreadSearchTermsData::SetGoogleBaseURL("https://www.google.com/"); SetUserSelectedDefaultSearchProvider("{google:baseURL}"); instant_service_ = InstantServiceFactory::GetForProfile(profile()); + + instant_service_->SetImageFetcherForTesting( + new testing::NiceMock<image_fetcher::MockImageFetcher>()); } void InstantUnitTestBase::TearDown() {
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 9c7f737..78a50181 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1525,8 +1525,6 @@ "views/frame/native_browser_frame_factory_chromeos.cc", "views/frame/top_controls_slide_controller_chromeos.cc", "views/frame/top_controls_slide_controller_chromeos.h", - "views/ime_driver/input_method_bridge_chromeos.cc", - "views/ime_driver/input_method_bridge_chromeos.h", "views/platform_keys_certificate_selector_chromeos.cc", "views/platform_keys_certificate_selector_chromeos.h", "views/profiles/profile_indicator_icon.cc", @@ -3073,17 +3071,6 @@ ] } - if (enable_mus) { - sources += [ - "views/ime_driver/ime_driver_mus.cc", - "views/ime_driver/ime_driver_mus.h", - "views/ime_driver/remote_text_input_client.cc", - "views/ime_driver/remote_text_input_client.h", - "views/ime_driver/simple_input_method.cc", - "views/ime_driver/simple_input_method.h", - ] - } - if (is_win) { sources += [ "views/chrome_views_delegate_win.cc" ] }
diff --git a/chrome/browser/ui/app_list/app_list_client_impl.cc b/chrome/browser/ui/app_list/app_list_client_impl.cc index ebd5a317..5afe27a4f 100644 --- a/chrome/browser/ui/app_list/app_list_client_impl.cc +++ b/chrome/browser/ui/app_list/app_list_client_impl.cc
@@ -225,7 +225,7 @@ void AppListClientImpl::OnFolderCreated( int profile_id, - ash::mojom::AppListItemMetadataPtr item) { + std::unique_ptr<ash::AppListItemMetadata> item) { auto* requested_model_updater = profile_model_mappings_[profile_id]; if (!requested_model_updater) return; @@ -235,7 +235,7 @@ void AppListClientImpl::OnFolderDeleted( int profile_id, - ash::mojom::AppListItemMetadataPtr item) { + std::unique_ptr<ash::AppListItemMetadata> item) { auto* requested_model_updater = profile_model_mappings_[profile_id]; if (!requested_model_updater) return; @@ -243,8 +243,9 @@ requested_model_updater->OnFolderDeleted(std::move(item)); } -void AppListClientImpl::OnItemUpdated(int profile_id, - ash::mojom::AppListItemMetadataPtr item) { +void AppListClientImpl::OnItemUpdated( + int profile_id, + std::unique_ptr<ash::AppListItemMetadata> item) { auto* requested_model_updater = profile_model_mappings_[profile_id]; if (!requested_model_updater) return;
diff --git a/chrome/browser/ui/app_list/app_list_client_impl.h b/chrome/browser/ui/app_list/app_list_client_impl.h index ceff688..2796499 100644 --- a/chrome/browser/ui/app_list/app_list_client_impl.h +++ b/chrome/browser/ui/app_list/app_list_client_impl.h
@@ -70,11 +70,11 @@ void OnAppListTargetVisibilityChanged(bool visible) override; void OnAppListVisibilityChanged(bool visible) override; void OnFolderCreated(int profile_id, - ash::mojom::AppListItemMetadataPtr item) override; + std::unique_ptr<ash::AppListItemMetadata> item) override; void OnFolderDeleted(int profile_id, - ash::mojom::AppListItemMetadataPtr item) override; + std::unique_ptr<ash::AppListItemMetadata> item) override; void OnItemUpdated(int profile_id, - ash::mojom::AppListItemMetadataPtr item) override; + std::unique_ptr<ash::AppListItemMetadata> item) override; void OnPageBreakItemAdded(int profile_id, const std::string& id, const syncer::StringOrdinal& position) override;
diff --git a/chrome/browser/ui/app_list/app_list_model_updater.h b/chrome/browser/ui/app_list/app_list_model_updater.h index aa462f47..52476fa 100644 --- a/chrome/browser/ui/app_list/app_list_model_updater.h +++ b/chrome/browser/ui/app_list/app_list_model_updater.h
@@ -138,9 +138,12 @@ virtual bool SearchEngineIsGoogle() = 0; // Methods for handle model updates in ash: - virtual void OnFolderCreated(ash::mojom::AppListItemMetadataPtr item) = 0; - virtual void OnFolderDeleted(ash::mojom::AppListItemMetadataPtr item) = 0; - virtual void OnItemUpdated(ash::mojom::AppListItemMetadataPtr item) = 0; + virtual void OnFolderCreated( + std::unique_ptr<ash::AppListItemMetadata> item) = 0; + virtual void OnFolderDeleted( + std::unique_ptr<ash::AppListItemMetadata> item) = 0; + virtual void OnItemUpdated( + std::unique_ptr<ash::AppListItemMetadata> item) = 0; virtual void OnPageBreakItemAdded(const std::string& id, const syncer::StringOrdinal& position) = 0; virtual void OnPageBreakItemDeleted(const std::string& id) = 0;
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service.h b/chrome/browser/ui/app_list/app_list_syncable_service.h index f62c45b4..b04cbd5 100644 --- a/chrome/browser/ui/app_list/app_list_syncable_service.h +++ b/chrome/browser/ui/app_list/app_list_syncable_service.h
@@ -11,7 +11,6 @@ #include <memory> #include <string> -#include "ash/public/interfaces/app_list.mojom.h" #include "base/callback.h" #include "base/macros.h" #include "base/memory/weak_ptr.h"
diff --git a/chrome/browser/ui/app_list/chrome_app_list_item.cc b/chrome/browser/ui/app_list/chrome_app_list_item.cc index 28c223f..25708f2 100644 --- a/chrome/browser/ui/app_list/chrome_app_list_item.cc +++ b/chrome/browser/ui/app_list/chrome_app_list_item.cc
@@ -24,13 +24,11 @@ AppListControllerDelegate* g_controller_for_test = nullptr; -ash::mojom::AppListItemMetadataPtr CreateDefaultMetadata( +std::unique_ptr<ash::AppListItemMetadata> CreateDefaultMetadata( const std::string& app_id) { - return ash::mojom::AppListItemMetadata::New( - app_id, std::string() /* name */, std::string() /* short_name */, - std::string() /* folder_id */, syncer::StringOrdinal(), - false /* is_folder */, false /* is_persistent */, - gfx::ImageSkia() /* icon */, false /* is_page_break */); + auto metadata = std::make_unique<ash::AppListItemMetadata>(); + metadata->id = app_id; + return metadata; } } // namespace @@ -87,12 +85,13 @@ } void ChromeAppListItem::SetMetadata( - ash::mojom::AppListItemMetadataPtr metadata) { + std::unique_ptr<ash::AppListItemMetadata> metadata) { metadata_ = std::move(metadata); } -ash::mojom::AppListItemMetadataPtr ChromeAppListItem::CloneMetadata() const { - return metadata_.Clone(); +std::unique_ptr<ash::AppListItemMetadata> ChromeAppListItem::CloneMetadata() + const { + return std::make_unique<ash::AppListItemMetadata>(*metadata_); } void ChromeAppListItem::PerformActivate(int event_flags) {
diff --git a/chrome/browser/ui/app_list/chrome_app_list_item.h b/chrome/browser/ui/app_list/chrome_app_list_item.h index 4b9a617..3806c06 100644 --- a/chrome/browser/ui/app_list/chrome_app_list_item.h +++ b/chrome/browser/ui/app_list/chrome_app_list_item.h
@@ -9,6 +9,7 @@ #include <string> #include <utility> +#include "ash/public/cpp/app_list/app_list_types.h" #include "base/macros.h" #include "chrome/browser/ui/app_list/app_context_menu.h" #include "chrome/browser/ui/app_list/app_list_syncable_service.h" @@ -65,8 +66,8 @@ void SetIsInstalling(bool is_installing); void SetPercentDownloaded(int32_t percent_downloaded); - void SetMetadata(ash::mojom::AppListItemMetadataPtr metadata); - ash::mojom::AppListItemMetadataPtr CloneMetadata() const; + void SetMetadata(std::unique_ptr<ash::AppListItemMetadata> metadata); + std::unique_ptr<ash::AppListItemMetadata> CloneMetadata() const; // The following methods set Chrome side data here, and call model updater // interfaces that talk to ash directly. @@ -140,7 +141,7 @@ void MaybeDismissAppList(); private: - ash::mojom::AppListItemMetadataPtr metadata_; + std::unique_ptr<ash::AppListItemMetadata> metadata_; Profile* profile_; AppListModelUpdater* model_updater_ = nullptr;
diff --git a/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc b/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc index 6dbde0e..4c91cff 100644 --- a/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc +++ b/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc
@@ -35,7 +35,7 @@ return; // Activating this model updater should sync the cached model to Ash. - std::vector<ash::mojom::AppListItemMetadataPtr> items_to_sync; + std::vector<std::unique_ptr<ash::AppListItemMetadata>> items_to_sync; for (auto const& item : items_) items_to_sync.push_back(item.second->CloneMetadata()); @@ -46,7 +46,8 @@ void ChromeAppListModelUpdater::AddItem( std::unique_ptr<ChromeAppListItem> app_item) { - ash::mojom::AppListItemMetadataPtr item_data = app_item->CloneMetadata(); + std::unique_ptr<ash::AppListItemMetadata> item_data = + app_item->CloneMetadata(); // Add to Chrome first leave all updates to observer methods. AddChromeItem(std::move(app_item)); if (app_list_controller_) @@ -56,7 +57,8 @@ void ChromeAppListModelUpdater::AddItemToFolder( std::unique_ptr<ChromeAppListItem> app_item, const std::string& folder_id) { - ash::mojom::AppListItemMetadataPtr item_data = app_item->CloneMetadata(); + std::unique_ptr<ash::AppListItemMetadata> item_data = + app_item->CloneMetadata(); // Add to Chrome first leave all updates to observer methods. ChromeAppListItem* item_added = AddChromeItem(std::move(app_item)); item_added->SetChromeFolderId(folder_id); @@ -197,7 +199,7 @@ ChromeAppListItem* item = FindItem(id); if (!item) return; - ash::mojom::AppListItemMetadataPtr data = item->CloneMetadata(); + std::unique_ptr<ash::AppListItemMetadata> data = item->CloneMetadata(); data->name = name; app_list_controller_->SetItemMetadata(id, std::move(data)); } @@ -211,7 +213,7 @@ ChromeAppListItem* item = FindItem(id); if (!item) return; - ash::mojom::AppListItemMetadataPtr data = item->CloneMetadata(); + std::unique_ptr<ash::AppListItemMetadata> data = item->CloneMetadata(); data->name = name; data->short_name = short_name; app_list_controller_->SetItemMetadata(id, std::move(data)); @@ -225,7 +227,7 @@ ChromeAppListItem* item = FindItem(id); if (!item) return; - ash::mojom::AppListItemMetadataPtr data = item->CloneMetadata(); + std::unique_ptr<ash::AppListItemMetadata> data = item->CloneMetadata(); data->position = new_position; app_list_controller_->SetItemMetadata(id, std::move(data)); } @@ -237,7 +239,7 @@ ChromeAppListItem* item = FindItem(id); if (!item) return; - ash::mojom::AppListItemMetadataPtr data = item->CloneMetadata(); + std::unique_ptr<ash::AppListItemMetadata> data = item->CloneMetadata(); data->is_persistent = is_persistent; app_list_controller_->SetItemMetadata(id, std::move(data)); } @@ -249,7 +251,7 @@ ChromeAppListItem* item = FindItem(id); if (!item) return; - ash::mojom::AppListItemMetadataPtr data = item->CloneMetadata(); + std::unique_ptr<ash::AppListItemMetadata> data = item->CloneMetadata(); data->folder_id = folder_id; app_list_controller_->SetItemMetadata(id, std::move(data)); } @@ -407,7 +409,7 @@ base::BindOnce( [](base::WeakPtr<ChromeAppListModelUpdater> self, ResolveOemFolderPositionCallback callback, - ash::mojom::AppListItemMetadataPtr folder_data) { + std::unique_ptr<ash::AppListItemMetadata> folder_data) { if (!self) return; ChromeAppListItem* chrome_oem_folder = nullptr; @@ -435,8 +437,7 @@ oem_folder_name, position_to_try, base::BindOnce( [](base::WeakPtr<ChromeAppListModelUpdater> self, - std::unique_ptr<ChromeAppListItem> item, - ash::mojom::AppListItemMetadataPtr /* oem_folder */) { + std::unique_ptr<ChromeAppListItem> item) { if (!self) return; self->AddItemToFolder(std::move(item), ash::kOemFolderId); @@ -502,7 +503,7 @@ // Methods called from Ash: void ChromeAppListModelUpdater::OnFolderCreated( - ash::mojom::AppListItemMetadataPtr item) { + std::unique_ptr<ash::AppListItemMetadata> item) { DCHECK(item->is_folder); ChromeAppListItem* chrome_item = FindItem(item->id); // If the item already exists, we should have set its information properly. @@ -520,7 +521,7 @@ } void ChromeAppListModelUpdater::OnFolderDeleted( - ash::mojom::AppListItemMetadataPtr item) { + std::unique_ptr<ash::AppListItemMetadata> item) { DCHECK(item->is_folder); ChromeAppListItem* chrome_item = FindItem(item->id); @@ -534,7 +535,7 @@ } void ChromeAppListModelUpdater::OnItemUpdated( - ash::mojom::AppListItemMetadataPtr item) { + std::unique_ptr<ash::AppListItemMetadata> item) { ChromeAppListItem* chrome_item = FindItem(item->id); // Ignore the item if it does not exist. This happens when a race occurs
diff --git a/chrome/browser/ui/app_list/chrome_app_list_model_updater.h b/chrome/browser/ui/app_list/chrome_app_list_model_updater.h index a84b6b2..f172275 100644 --- a/chrome/browser/ui/app_list/chrome_app_list_model_updater.h +++ b/chrome/browser/ui/app_list/chrome_app_list_model_updater.h
@@ -108,9 +108,9 @@ bool update_folder) override; // Methods to handle model update from ash: - void OnFolderCreated(ash::mojom::AppListItemMetadataPtr item) override; - void OnFolderDeleted(ash::mojom::AppListItemMetadataPtr item) override; - void OnItemUpdated(ash::mojom::AppListItemMetadataPtr item) override; + void OnFolderCreated(std::unique_ptr<ash::AppListItemMetadata> item) override; + void OnFolderDeleted(std::unique_ptr<ash::AppListItemMetadata> item) override; + void OnItemUpdated(std::unique_ptr<ash::AppListItemMetadata> item) override; void OnPageBreakItemAdded(const std::string& id, const syncer::StringOrdinal& position) override; void OnPageBreakItemDeleted(const std::string& id) override;
diff --git a/chrome/browser/ui/app_list/crostini/crostini_app_model_builder_unittest.cc b/chrome/browser/ui/app_list/crostini/crostini_app_model_builder_unittest.cc index 2ff8198..2bf52eed 100644 --- a/chrome/browser/ui/app_list/crostini/crostini_app_model_builder_unittest.cc +++ b/chrome/browser/ui/app_list/crostini/crostini_app_model_builder_unittest.cc
@@ -315,8 +315,7 @@ // We simulate ash creating the crostini folder and calling back into chrome // (rather than use a full browser test). - ash::mojom::AppListItemMetadataPtr metadata = - ash::mojom::AppListItemMetadata::New(); + auto metadata = std::make_unique<ash::AppListItemMetadata>(); metadata->id = crostini::kCrostiniFolderId; GetModelUpdater()->OnFolderCreated(std::move(metadata));
diff --git a/chrome/browser/ui/app_list/test/chrome_app_list_test_support.cc b/chrome/browser/ui/app_list/test/chrome_app_list_test_support.cc index 4dfcc4c2..b4c2de4 100644 --- a/chrome/browser/ui/app_list/test/chrome_app_list_test_support.cc +++ b/chrome/browser/ui/app_list/test/chrome_app_list_test_support.cc
@@ -4,9 +4,11 @@ #include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h" +#include <memory> #include <string> #include "ash/public/cpp/app_list/app_list_config.h" +#include "ash/public/cpp/app_list/app_list_types.h" #include "ash/public/interfaces/app_list_view.mojom.h" #include "base/bind.h" #include "base/macros.h" @@ -97,11 +99,12 @@ const std::string app_id = crx_file::id_util::GenerateId(app_name); auto item = std::make_unique<ChromeAppListItem>(profile, app_id, model_updater); - gfx::ImageSkia icon = CreateImageSkia(i); - item->SetMetadata(ash::mojom::AppListItemMetadata::New( - app_id, app_name, /*short_name=*/app_name, /*folder_id=*/"", - syncer::StringOrdinal(app_id), /*is_folder=*/false, - /*is_persistent=*/false, icon, /*is_page_break=*/false)); + auto metadata = std::make_unique<ash::AppListItemMetadata>(); + metadata->id = app_id; + metadata->name = app_name; + metadata->short_name = app_name; + metadata->icon = CreateImageSkia(i); + item->SetMetadata(std::move(metadata)); model_updater->AddItem(std::move(item)); } // Wait for the AddItem mojo calls to be handled by Ash. Note that
diff --git a/chrome/browser/ui/app_list/test/fake_app_list_model_updater.cc b/chrome/browser/ui/app_list/test/fake_app_list_model_updater.cc index 6fded37..4ce990f 100644 --- a/chrome/browser/ui/app_list/test/fake_app_list_model_updater.cc +++ b/chrome/browser/ui/app_list/test/fake_app_list_model_updater.cc
@@ -144,13 +144,12 @@ search_results_ = results; } -ash::mojom::AppListItemMetadataPtr -FakeAppListModelUpdater::FindOrCreateOemFolder( +void FakeAppListModelUpdater::FindOrCreateOemFolder( const std::string& oem_folder_name, const syncer::StringOrdinal& preferred_oem_position) { ChromeAppListItem* oem_folder = FindFolderItem(ash::kOemFolderId); if (oem_folder) { - ash::mojom::AppListItemMetadataPtr folder_data = + std::unique_ptr<ash::AppListItemMetadata> folder_data = oem_folder->CloneMetadata(); folder_data->name = oem_folder_name; oem_folder->SetMetadata(std::move(folder_data)); @@ -159,7 +158,7 @@ std::make_unique<ChromeAppListItem>(nullptr, ash::kOemFolderId, nullptr); oem_folder = new_folder.get(); - ash::mojom::AppListItemMetadataPtr folder_data = + std::unique_ptr<ash::AppListItemMetadata> folder_data = oem_folder->CloneMetadata(); folder_data->position = preferred_oem_position.IsValid() ? preferred_oem_position @@ -168,7 +167,6 @@ oem_folder->SetMetadata(std::move(folder_data)); AddItem(std::move(new_folder)); } - return oem_folder->CloneMetadata(); } syncer::StringOrdinal FakeAppListModelUpdater::GetOemFolderPos() { @@ -216,7 +214,7 @@ } void FakeAppListModelUpdater::OnFolderCreated( - ash::mojom::AppListItemMetadataPtr folder) { + std::unique_ptr<ash::AppListItemMetadata> folder) { std::unique_ptr<ChromeAppListItem> stub_folder = std::make_unique<ChromeAppListItem>(profile_, folder->id, this);
diff --git a/chrome/browser/ui/app_list/test/fake_app_list_model_updater.h b/chrome/browser/ui/app_list/test/fake_app_list_model_updater.h index 97f4620..50ad427 100644 --- a/chrome/browser/ui/app_list/test/fake_app_list_model_updater.h +++ b/chrome/browser/ui/app_list/test/fake_app_list_model_updater.h
@@ -62,9 +62,11 @@ return search_results_; } - void OnFolderCreated(ash::mojom::AppListItemMetadataPtr folder) override; - void OnFolderDeleted(ash::mojom::AppListItemMetadataPtr item) override {} - void OnItemUpdated(ash::mojom::AppListItemMetadataPtr item) override {} + void OnFolderCreated( + std::unique_ptr<ash::AppListItemMetadata> folder) override; + void OnFolderDeleted( + std::unique_ptr<ash::AppListItemMetadata> item) override {} + void OnItemUpdated(std::unique_ptr<ash::AppListItemMetadata> item) override {} void OnPageBreakItemAdded(const std::string& id, const syncer::StringOrdinal& position) override {} void OnPageBreakItemDeleted(const std::string& id) override {} @@ -79,7 +81,7 @@ base::ObserverList<AppListModelUpdaterObserver> observers_; Profile* profile_; - ash::mojom::AppListItemMetadataPtr FindOrCreateOemFolder( + void FindOrCreateOemFolder( const std::string& oem_folder_name, const syncer::StringOrdinal& preferred_oem_position); syncer::StringOrdinal GetOemFolderPos();
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc index efb656b..fc67f4c41 100644 --- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc +++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
@@ -43,7 +43,6 @@ #include "chrome/browser/ui/ash/tablet_mode_client.h" #include "chrome/browser/ui/ash/vpn_list_forwarder.h" #include "chrome/browser/ui/ash/wallpaper_controller_client.h" -#include "chrome/browser/ui/views/ime_driver/ime_driver_mus.h" #include "chrome/browser/ui/views/select_file_dialog_extension.h" #include "chrome/browser/ui/views/select_file_dialog_extension_factory.h" #include "chromeos/network/network_connect.h" @@ -62,7 +61,6 @@ #include "content/public/common/service_manager_connection.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/service_manager/public/cpp/connector.h" -#include "services/ws/public/mojom/user_activity_monitor.mojom.h" #include "ui/base/ime/chromeos/input_method_manager.h" #include "ui/base/ui_base_features.h" @@ -120,9 +118,6 @@ } void ChromeBrowserMainExtraPartsAsh::PreProfileInit() { - // IME driver must be available at login screen, so initialize before profile. - IMEDriverMus::Register(); - // NetworkConnect handles the network connection state machine for the UI. network_connect_delegate_ = std::make_unique<NetworkConnectDelegateChromeOS>();
diff --git a/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc b/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc index 4451059..6e6de86f 100644 --- a/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc +++ b/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc
@@ -378,11 +378,9 @@ return; auto* controller = keyboard::KeyboardController::Get(); - EXPECT_EQ(controller->GetStateForTest(), - keyboard::KeyboardControllerState::kLoadingExtension); + EXPECT_EQ(controller->GetStateForTest(), keyboard::KeyboardUIState::kLoading); KeyboardLoadedWaiter().Wait(); - EXPECT_EQ(controller->GetStateForTest(), - keyboard::KeyboardControllerState::kHidden); + EXPECT_EQ(controller->GetStateForTest(), keyboard::KeyboardUIState::kHidden); } IN_PROC_BROWSER_TEST_F(KeyboardControllerStateTest, @@ -393,18 +391,15 @@ auto* controller = keyboard::KeyboardController::Get(); controller->ShowKeyboard(false); // Need to wait the extension to be loaded. Hence LOADING_EXTENSION. - EXPECT_EQ(controller->GetStateForTest(), - keyboard::KeyboardControllerState::kLoadingExtension); + EXPECT_EQ(controller->GetStateForTest(), keyboard::KeyboardUIState::kLoading); KeyboardVisibleWaiter(true).Wait(); controller->HideKeyboardExplicitlyBySystem(); - EXPECT_EQ(controller->GetStateForTest(), - keyboard::KeyboardControllerState::kHidden); + EXPECT_EQ(controller->GetStateForTest(), keyboard::KeyboardUIState::kHidden); controller->ShowKeyboard(false); // The extension already has been loaded. Hence SHOWING. - EXPECT_EQ(controller->GetStateForTest(), - keyboard::KeyboardControllerState::kShown); + EXPECT_EQ(controller->GetStateForTest(), keyboard::KeyboardUIState::kShown); } // See crbug.com/755354. @@ -415,10 +410,8 @@ auto* controller = keyboard::KeyboardController::Get(); - EXPECT_EQ(controller->GetStateForTest(), - keyboard::KeyboardControllerState::kLoadingExtension); + EXPECT_EQ(controller->GetStateForTest(), keyboard::KeyboardUIState::kLoading); controller->Shutdown(); - EXPECT_EQ(controller->GetStateForTest(), - keyboard::KeyboardControllerState::kInitial); + EXPECT_EQ(controller->GetStateForTest(), keyboard::KeyboardUIState::kInitial); }
diff --git a/chrome/browser/ui/input_method/input_method_engine.cc b/chrome/browser/ui/input_method/input_method_engine.cc index cc13e14..5ab21b2d 100644 --- a/chrome/browser/ui/input_method/input_method_engine.cc +++ b/chrome/browser/ui/input_method/input_method_engine.cc
@@ -89,6 +89,14 @@ } } +bool InputMethodEngine::SetCompositionRange( + uint32_t before, + uint32_t after, + const std::vector<ui::ImeTextSpan>& text_spans) { + // Not supported on non-Chrome OS platforms. + return false; +} + void InputMethodEngine::CommitTextToInputContext(int context_id, const std::string& text) { ui::IMEInputContextHandlerInterface* input_context =
diff --git a/chrome/browser/ui/input_method/input_method_engine.h b/chrome/browser/ui/input_method/input_method_engine.h index 29b3433..9293e0d 100644 --- a/chrome/browser/ui/input_method/input_method_engine.h +++ b/chrome/browser/ui/input_method/input_method_engine.h
@@ -31,6 +31,10 @@ void UpdateComposition(const ui::CompositionText& composition_text, uint32_t cursor_pos, bool is_visible) override; + bool SetCompositionRange( + uint32_t before, + uint32_t after, + const std::vector<ui::ImeTextSpan>& text_spans) override; void CommitTextToInputContext(int context_id, const std::string& text) override; void DeleteSurroundingTextToInputContext(int offset,
diff --git a/chrome/browser/ui/input_method/input_method_engine_base.cc b/chrome/browser/ui/input_method/input_method_engine_base.cc index 84d09486..8df1347 100644 --- a/chrome/browser/ui/input_method/input_method_engine_base.cc +++ b/chrome/browser/ui/input_method/input_method_engine_base.cc
@@ -404,6 +404,50 @@ return true; } +bool InputMethodEngineBase::SetCompositionRange( + int context_id, + int selection_before, + int selection_after, + const std::vector<SegmentInfo>& segments, + std::string* error) { + if (!IsActive()) { + *error = kErrorNotActive; + return false; + } + if (context_id != context_id_ || context_id_ == -1) { + *error = kErrorWrongContext; + return false; + } + + // Can't change composition range when there's pending composition text. + if (!composition_text_->text.empty()) + return false; + + std::vector<ui::ImeTextSpan> text_spans; + for (const auto& segment : segments) { + ui::ImeTextSpan text_span; + + text_span.underline_color = SK_ColorTRANSPARENT; + switch (segment.style) { + case SEGMENT_STYLE_UNDERLINE: + text_span.thickness = ui::ImeTextSpan::Thickness::kThin; + break; + case SEGMENT_STYLE_DOUBLE_UNDERLINE: + text_span.thickness = ui::ImeTextSpan::Thickness::kThick; + break; + case SEGMENT_STYLE_NO_UNDERLINE: + text_span.thickness = ui::ImeTextSpan::Thickness::kNone; + break; + } + + text_span.start_offset = segment.start; + text_span.end_offset = segment.end; + text_spans.push_back(text_span); + } + + return SetCompositionRange(selection_before, selection_after, text_spans); +} + void InputMethodEngineBase::KeyEventHandled(const std::string& extension_id, const std::string& request_id, bool handled) {
diff --git a/chrome/browser/ui/input_method/input_method_engine_base.h b/chrome/browser/ui/input_method/input_method_engine_base.h index 9855ad31..fb8757de 100644 --- a/chrome/browser/ui/input_method/input_method_engine_base.h +++ b/chrome/browser/ui/input_method/input_method_engine_base.h
@@ -183,6 +183,14 @@ int cursor, const std::vector<SegmentInfo>& segments, std::string* error); + + // Set the current composition range. + bool SetCompositionRange(int context_id, + int selection_before, + int selection_after, + const std::vector<SegmentInfo>& segments, + std::string* error); + // Called when a key event is handled. void KeyEventHandled(const std::string& extension_id, const std::string& request_id, @@ -208,6 +216,11 @@ virtual void UpdateComposition(const ui::CompositionText& composition_text, uint32_t cursor_pos, bool is_visible) = 0; + // Notifies InputContextHandler to change the composition range. + virtual bool SetCompositionRange( + uint32_t before, + uint32_t after, + const std::vector<ui::ImeTextSpan>& text_spans) = 0; // Notifies InputContextHanlder to commit |text|. virtual void CommitTextToInputContext(int context_id, const std::string& text) = 0;
diff --git a/chrome/browser/ui/search/local_ntp_backgrounds_browsertest.cc b/chrome/browser/ui/search/local_ntp_backgrounds_browsertest.cc index 4fdcc11..b35c9ed 100644 --- a/chrome/browser/ui/search/local_ntp_backgrounds_browsertest.cc +++ b/chrome/browser/ui/search/local_ntp_backgrounds_browsertest.cc
@@ -21,15 +21,27 @@ #include "chrome/common/search/instant_types.h" #include "chrome/common/url_constants.h" #include "chrome/test/base/in_process_browser_test.h" +#include "components/image_fetcher/core/mock_image_fetcher.h" #include "content/public/browser/web_contents.h" #include "content/public/test/test_utils.h" #include "extensions/browser/extension_registry.h" #include "testing/gtest/include/gtest/gtest.h" -namespace { - using LocalNTPCustomBackgroundsTest = InProcessBrowserTest; +class TestInstantService { + public: + explicit TestInstantService(Profile* profile) { + instant_service = InstantServiceFactory::GetForProfile(profile); + instant_service->SetImageFetcherForTesting( + new testing::NiceMock<image_fetcher::MockImageFetcher>()); + } + InstantService* get_instant_service() { return instant_service; } + + private: + InstantService* instant_service; +}; + IN_PROC_BROWSER_TEST_F(LocalNTPCustomBackgroundsTest, EmbeddedSearchAPIEndToEnd) { content::WebContents* active_tab = @@ -41,9 +53,9 @@ local_ntp_test_utils::NavigateToNTPAndWaitUntilLoaded(browser()); // Check that a URL with no attributions can be set. - InstantService* instant_service = - InstantServiceFactory::GetForProfile(browser()->profile()); - instant_service->AddValidBackdropUrlForTesting(GURL("https://www.test.com/")); + TestInstantService test_instant_service(browser()->profile()); + test_instant_service.get_instant_service()->AddValidBackdropUrlForTesting( + GURL("https://www.test.com/")); EXPECT_TRUE(content::ExecuteScript(active_tab, "window.chrome.embeddedSearch.newTabPage." "setBackgroundURL('https://www.test.com/" @@ -76,9 +88,9 @@ local_ntp_test_utils::NavigateToNTPAndWaitUntilLoaded(browser()); // Set a custom background attribution via the EmbeddedSearch API. - InstantService* instant_service = - InstantServiceFactory::GetForProfile(browser()->profile()); - instant_service->AddValidBackdropUrlForTesting(GURL("https://www.test.com/")); + TestInstantService test_instant_service(browser()->profile()); + test_instant_service.get_instant_service()->AddValidBackdropUrlForTesting( + GURL("https://www.test.com/")); EXPECT_TRUE(content::ExecuteScript(active_tab, "window.chrome.embeddedSearch.newTabPage." "setBackgroundURLWithAttributions('https:/" @@ -120,9 +132,8 @@ local_ntp_test_utils::NavigateToNTPAndWaitUntilLoaded(browser()); // Set a custom background image via the EmbeddedSearch API. - InstantService* instant_service = - InstantServiceFactory::GetForProfile(browser()->profile()); - instant_service->AddValidBackdropUrlForTesting( + TestInstantService test_instant_service(browser()->profile()); + test_instant_service.get_instant_service()->AddValidBackdropUrlForTesting( GURL("chrome-search://local-ntp/background1.jpg")); EXPECT_TRUE(content::ExecuteScript( active_tab, @@ -166,9 +177,8 @@ local_ntp_test_utils::NavigateToNTPAndWaitUntilLoaded(browser()); // Set a custom background image via the EmbeddedSearch API. - InstantService* instant_service = - InstantServiceFactory::GetForProfile(browser()->profile()); - instant_service->AddValidBackdropUrlForTesting( + TestInstantService test_instant_service(browser()->profile()); + test_instant_service.get_instant_service()->AddValidBackdropUrlForTesting( GURL("chrome-search://local-ntp/background1.jpg")); ASSERT_TRUE(content::ExecuteScript( active_tab, @@ -268,9 +278,9 @@ local_ntp_test_utils::NavigateToNTPAndWaitUntilLoaded(browser()); // Set a custom background attribution via the EmbeddedSearch API. - InstantService* instant_service = - InstantServiceFactory::GetForProfile(profile()); - instant_service->AddValidBackdropUrlForTesting(GURL("https://www.test.com/")); + TestInstantService test_instant_service(browser()->profile()); + test_instant_service.get_instant_service()->AddValidBackdropUrlForTesting( + GURL("https://www.test.com/")); ASSERT_TRUE(content::ExecuteScript(active_tab, "window.chrome.embeddedSearch.newTabPage." "setBackgroundURLWithAttributions('https:/" @@ -327,9 +337,8 @@ local_ntp_test_utils::NavigateToNTPAndWaitUntilLoaded(browser()); // Set a custom background image via the EmbeddedSearch API. - InstantService* instant_service = - InstantServiceFactory::GetForProfile(profile()); - instant_service->AddValidBackdropUrlForTesting( + TestInstantService test_instant_service(browser()->profile()); + test_instant_service.get_instant_service()->AddValidBackdropUrlForTesting( GURL("chrome-search://local-ntp/background1.jpg")); ASSERT_TRUE(content::ExecuteScript( active_tab, @@ -392,9 +401,8 @@ EXPECT_TRUE(result); // Set a custom background image via the EmbeddedSearch API. - InstantService* instant_service = - InstantServiceFactory::GetForProfile(profile()); - instant_service->AddValidBackdropUrlForTesting( + TestInstantService test_instant_service(browser()->profile()); + test_instant_service.get_instant_service()->AddValidBackdropUrlForTesting( GURL("chrome-search://local-ntp/background1.jpg")); ASSERT_TRUE(content::ExecuteScript( active_tab, @@ -440,6 +448,8 @@ InstantServiceFactory::GetForProfile(browser()->profile()); theme()->SetDarkMode(true); instant_service->SetDarkModeThemeForTesting(theme()); + instant_service->SetImageFetcherForTesting( + new testing::NiceMock<image_fetcher::MockImageFetcher>()); } InstantService* instant_service; @@ -534,5 +544,3 @@ EXPECT_TRUE(GetIsDarkModeApplied(active_tab)); EXPECT_TRUE(GetIsLightChipsApplied(active_tab)); } - -} // namespace
diff --git a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc index d762118..79581831 100644 --- a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc +++ b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc
@@ -27,7 +27,6 @@ #include "content/public/common/service_manager_connection.h" #include "services/service_manager/public/cpp/connector.h" #include "services/ws/public/cpp/gpu/gpu.h" // nogncheck -#include "services/ws/public/mojom/constants.mojom.h" #include "ui/display/screen.h" #include "ui/views/widget/desktop_aura/desktop_screen.h" #include "ui/wm/core/wm_state.h"
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc b/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc index 7a1e16e2..3a42b08 100644 --- a/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc +++ b/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc
@@ -11,7 +11,8 @@ #include "chrome/browser/ui/views/extensions/extensions_toolbar_button.h" ExtensionsToolbarContainer::ExtensionsToolbarContainer(Browser* browser) - : browser_(browser), + : ToolbarIconContainerView(/*uses_highlight=*/true), + browser_(browser), model_(ToolbarActionsModel::Get(browser_->profile())), model_observer_(this), extensions_button_(new ExtensionsToolbarButton(browser_, this)) {
diff --git a/chrome/browser/ui/views/ime_driver/OWNERS b/chrome/browser/ui/views/ime_driver/OWNERS deleted file mode 100644 index 1d9f31f..0000000 --- a/chrome/browser/ui/views/ime_driver/OWNERS +++ /dev/null
@@ -1,5 +0,0 @@ -# For mash / mustash. -xiyuan@chromium.org - -# For general IME. -file://ui/base/ime/OWNERS
diff --git a/chrome/browser/ui/views/ime_driver/ime_driver_mus.cc b/chrome/browser/ui/views/ime_driver/ime_driver_mus.cc deleted file mode 100644 index a7e2d97..0000000 --- a/chrome/browser/ui/views/ime_driver/ime_driver_mus.cc +++ /dev/null
@@ -1,59 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/ime_driver/ime_driver_mus.h" - -#include <memory> -#include <utility> - -#include "chrome/browser/ui/views/ime_driver/remote_text_input_client.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/common/service_manager_connection.h" -#include "mojo/public/cpp/bindings/strong_binding.h" -#include "services/service_manager/public/cpp/connector.h" -#include "services/ws/public/mojom/constants.mojom.h" -#include "services/ws/public/mojom/ime/ime.mojom.h" -#include "ui/base/ime/ime_bridge.h" - -#if defined(OS_CHROMEOS) -#include "chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.h" -#else -#include "chrome/browser/ui/views/ime_driver/simple_input_method.h" -#endif // defined(OS_CHROMEOS) - -IMEDriverMus::IMEDriverMus() { - ui::IMEBridge::Initialize(); -} - -IMEDriverMus::~IMEDriverMus() {} - -// static -void IMEDriverMus::Register() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - ws::mojom::IMEDriverPtr ime_driver_ptr; - mojo::MakeStrongBinding(std::make_unique<IMEDriverMus>(), - MakeRequest(&ime_driver_ptr)); - ws::mojom::IMERegistrarPtr ime_registrar; - content::ServiceManagerConnection::GetForProcess() - ->GetConnector() - ->BindInterface(ws::mojom::kServiceName, &ime_registrar); - ime_registrar->RegisterDriver(std::move(ime_driver_ptr)); -} - -void IMEDriverMus::StartSession( - ws::mojom::InputMethodRequest input_method_request, - ws::mojom::TextInputClientPtr client, - ws::mojom::SessionDetailsPtr details) { -#if defined(OS_CHROMEOS) - std::unique_ptr<RemoteTextInputClient> remote_client = - std::make_unique<RemoteTextInputClient>(std::move(client), - std::move(details)); - mojo::MakeStrongBinding( - std::make_unique<InputMethodBridge>(std::move(remote_client)), - std::move(input_method_request)); -#else - mojo::MakeStrongBinding(std::make_unique<SimpleInputMethod>(), - std::move(input_method_request)); -#endif -}
diff --git a/chrome/browser/ui/views/ime_driver/ime_driver_mus.h b/chrome/browser/ui/views/ime_driver/ime_driver_mus.h deleted file mode 100644 index 53ed4ba..0000000 --- a/chrome/browser/ui/views/ime_driver/ime_driver_mus.h +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_VIEWS_IME_DRIVER_IME_DRIVER_MUS_H_ -#define CHROME_BROWSER_UI_VIEWS_IME_DRIVER_IME_DRIVER_MUS_H_ - -#include "base/macros.h" -#include "services/ws/public/mojom/ime/ime.mojom.h" - -// Creates an InputMethodBridge when an IME session is started via mojo. -class IMEDriverMus : public ws::mojom::IMEDriver { - public: - IMEDriverMus(); - ~IMEDriverMus() override; - - // Instantiate the IME driver and register it to the UI service. - static void Register(); - - private: - // ws::mojom::IMEDriver: - void StartSession(ws::mojom::InputMethodRequest input_method_request, - ws::mojom::TextInputClientPtr client, - ws::mojom::SessionDetailsPtr details) override; - - DISALLOW_COPY_AND_ASSIGN(IMEDriverMus); -}; - -#endif // CHROME_BROWSER_UI_VIEWS_IME_DRIVER_IME_DRIVER_MUS_H_
diff --git a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc deleted file mode 100644 index 18470f0..0000000 --- a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc +++ /dev/null
@@ -1,84 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.h" - -#include <memory> -#include <utility> - -#include "chrome/browser/chromeos/accessibility/accessibility_input_method_observer.h" -#include "chrome/browser/ui/views/ime_driver/remote_text_input_client.h" -#include "ui/base/ime/chromeos/input_method_chromeos.h" -#include "ui/base/ime/ime_bridge.h" - -namespace { - -bool IsActiveInputContextHandler(ui::InputMethodChromeOS* input_method) { - ui::IMEBridge* bridge = ui::IMEBridge::Get(); - return bridge && bridge->GetInputContextHandler() == input_method; -} - -} // namespace - -InputMethodBridge::InputMethodBridge( - std::unique_ptr<RemoteTextInputClient> client) - : client_(std::move(client)), - input_method_chromeos_( - std::make_unique<ui::InputMethodChromeOS>(client_.get())), - accessibility_input_method_observer_( - std::make_unique<AccessibilityInputMethodObserver>( - input_method_chromeos_.get())) { - input_method_chromeos_->OnFocus(); - input_method_chromeos_->SetFocusedTextInputClient(client_.get()); -} - -InputMethodBridge::~InputMethodBridge() { - // IME session is ending. - if (IsActiveInputContextHandler(input_method_chromeos_.get())) - accessibility_input_method_observer_->ResetCaretBounds(); -} - -void InputMethodBridge::OnTextInputStateChanged( - ws::mojom::TextInputStatePtr text_input_state) { - client_->SetTextInputState(std::move(text_input_state)); - - if (IsActiveInputContextHandler(input_method_chromeos_.get())) - input_method_chromeos_->OnTextInputTypeChanged(client_.get()); -} - -void InputMethodBridge::OnCaretBoundsChanged(const gfx::Rect& caret_bounds) { - client_->SetCaretBounds(caret_bounds); - - if (IsActiveInputContextHandler(input_method_chromeos_.get())) - input_method_chromeos_->OnCaretBoundsChanged(client_.get()); -} - -void InputMethodBridge::OnTextInputClientDataChanged( - ws::mojom::TextInputClientDataPtr data) { - client_->SetTextInputClientData(std::move(data)); -} - -void InputMethodBridge::ProcessKeyEvent(std::unique_ptr<ui::Event> event, - ProcessKeyEventCallback callback) { - DCHECK(event->IsKeyEvent()); - ui::KeyEvent* key_event = event->AsKeyEvent(); - if (IsActiveInputContextHandler(input_method_chromeos_.get()) && - !key_event->is_char()) { - input_method_chromeos_->DispatchKeyEventAsync(key_event, - std::move(callback)); - } else { - const bool handled = false; - std::move(callback).Run(handled); - } -} - -void InputMethodBridge::CancelComposition() { - if (IsActiveInputContextHandler(input_method_chromeos_.get())) - input_method_chromeos_->CancelComposition(client_.get()); -} - -void InputMethodBridge::ShowVirtualKeyboardIfEnabled() { - if (IsActiveInputContextHandler(input_method_chromeos_.get())) - input_method_chromeos_->ShowVirtualKeyboardIfEnabled(); -}
diff --git a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.h b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.h deleted file mode 100644 index b98d214..0000000 --- a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.h +++ /dev/null
@@ -1,50 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_VIEWS_IME_DRIVER_INPUT_METHOD_BRIDGE_CHROMEOS_H_ -#define CHROME_BROWSER_UI_VIEWS_IME_DRIVER_INPUT_METHOD_BRIDGE_CHROMEOS_H_ - -#include "chrome/browser/ui/views/ime_driver/remote_text_input_client.h" -#include "services/ws/public/mojom/ime/ime.mojom.h" - -class AccessibilityInputMethodObserver; - -namespace ui { -class InputMethodChromeOS; -} - -// This bridges between mojo InputMethod API and ui::InputMethodChromeOS. It -// forwards the received events to an instance of ui::InputMethodChromeOS. -// Under mash this object is created and destroyed as top-level windows gain -// focus and start IME sessions. -// NOTE: There may be multiple instances of InputMethodChromeOS. In classic ash -// there is one instance shared by ash and browser, plus one per remote app -// (e.g. shortcut viewer). -class InputMethodBridge : public ws::mojom::InputMethod { - public: - explicit InputMethodBridge(std::unique_ptr<RemoteTextInputClient> client); - ~InputMethodBridge() override; - - // ws::mojom::InputMethod: - void OnTextInputStateChanged( - ws::mojom::TextInputStatePtr text_input_state) override; - void OnCaretBoundsChanged(const gfx::Rect& caret_bounds) override; - void OnTextInputClientDataChanged( - ws::mojom::TextInputClientDataPtr data) override; - void ProcessKeyEvent(std::unique_ptr<ui::Event> key_event, - ProcessKeyEventCallback callback) override; - void CancelComposition() override; - void ShowVirtualKeyboardIfEnabled() override; - - private: - std::unique_ptr<RemoteTextInputClient> client_; - std::unique_ptr<ui::InputMethodChromeOS> input_method_chromeos_; - // Must be destroyed before |input_method_chromeos_|. - std::unique_ptr<AccessibilityInputMethodObserver> - accessibility_input_method_observer_; - - DISALLOW_COPY_AND_ASSIGN(InputMethodBridge); -}; - -#endif // CHROME_BROWSER_UI_VIEWS_IME_DRIVER_INPUT_METHOD_BRIDGE_CHROMEOS_H_
diff --git a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos_unittest.cc b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos_unittest.cc deleted file mode 100644 index e44aa19bb..0000000 --- a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos_unittest.cc +++ /dev/null
@@ -1,275 +0,0 @@ -// 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 <stdint.h> - -#include <memory> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/run_loop.h" -#include "base/stl_util.h" -#include "base/strings/utf_string_conversions.h" -#include "chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.h" -#include "content/public/test/test_browser_thread_bundle.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/ime/ime_bridge.h" -#include "ui/events/event.h" -#include "ui/events/event_constants.h" -#include "ui/events/event_utils.h" -#include "ui/events/keycodes/dom/dom_code.h" -#include "ui/events/keycodes/dom/dom_key.h" -#include "ui/events/keycodes/keyboard_code_conversion.h" -#include "ui/events/keycodes/keyboard_codes.h" - -enum class CompositionEventType { - SET, - CONFIRM, - CLEAR, - INSERT_TEXT, - INSERT_CHAR -}; - -struct CompositionEvent { - CompositionEventType type; - base::string16 text_data; - base::char16 char_data; -}; - -class TestTextInputClient : public ws::mojom::TextInputClient { - public: - explicit TestTextInputClient(ws::mojom::TextInputClientRequest request) - : binding_(this, std::move(request)) {} - - CompositionEvent WaitUntilCompositionEvent() { - if (!receieved_event_.has_value()) { - run_loop_ = std::make_unique<base::RunLoop>(); - run_loop_->Run(); - run_loop_.reset(); - } - CompositionEvent result = receieved_event_.value(); - receieved_event_.reset(); - return result; - } - - void set_manual_ack_dispatch_key_event_post_ime_callback(bool manual) { - manual_ack_dispatch_key_event_post_ime_callback_ = manual; - } - - void AckDispatchKeyEventPostIMECallback() { - DCHECK(manual_ack_dispatch_key_event_post_ime_callback_); - - if (!pending_dispatch_key_event_post_ime_callback_) { - pending_dispatch_key_event_post_ime_callback_wait_loop_ = - std::make_unique<base::RunLoop>(); - pending_dispatch_key_event_post_ime_callback_wait_loop_->Run(); - pending_dispatch_key_event_post_ime_callback_wait_loop_.reset(); - } - - std::move(pending_dispatch_key_event_post_ime_callback_).Run(false, false); - } - - private: - void SetCompositionText(const ui::CompositionText& composition) override { - CompositionEvent ev = {CompositionEventType::SET, composition.text, 0}; - receieved_event_ = ev; - if (run_loop_) - run_loop_->Quit(); - } - void ConfirmCompositionText() override { - CompositionEvent ev = {CompositionEventType::CONFIRM, base::string16(), 0}; - receieved_event_ = ev; - if (run_loop_) - run_loop_->Quit(); - } - void ClearCompositionText() override { - CompositionEvent ev = {CompositionEventType::CLEAR, base::string16(), 0}; - receieved_event_ = ev; - if (run_loop_) - run_loop_->Quit(); - } - void InsertText(const base::string16& text) override { - CompositionEvent ev = {CompositionEventType::INSERT_TEXT, text, 0}; - receieved_event_ = ev; - if (run_loop_) - run_loop_->Quit(); - } - void InsertChar(std::unique_ptr<ui::Event> event) override { - ASSERT_TRUE(event->IsKeyEvent()); - CompositionEvent ev = {CompositionEventType::INSERT_CHAR, base::string16(), - event->AsKeyEvent()->GetCharacter()}; - receieved_event_ = ev; - if (run_loop_) - run_loop_->Quit(); - } - void DispatchKeyEventPostIME( - std::unique_ptr<ui::Event> event, - DispatchKeyEventPostIMECallback callback) override { - if (manual_ack_dispatch_key_event_post_ime_callback_) { - // Only one pending callback is expected. - EXPECT_FALSE(pending_dispatch_key_event_post_ime_callback_); - pending_dispatch_key_event_post_ime_callback_ = std::move(callback); - if (pending_dispatch_key_event_post_ime_callback_wait_loop_) - pending_dispatch_key_event_post_ime_callback_wait_loop_->Quit(); - return; - } - - std::move(callback).Run(false, false); - } - void EnsureCaretNotInRect(const gfx::Rect& rect) override {} - void SetEditableSelectionRange(const gfx::Range& range) override {} - void DeleteRange(const gfx::Range& range) override {} - void OnInputMethodChanged() override {} - void ChangeTextDirectionAndLayoutAlignment( - base::i18n::TextDirection direction) override {} - void ExtendSelectionAndDelete(uint32_t before, uint32_t after) override {} - - mojo::Binding<ws::mojom::TextInputClient> binding_; - std::unique_ptr<base::RunLoop> run_loop_; - base::Optional<CompositionEvent> receieved_event_; - - bool manual_ack_dispatch_key_event_post_ime_callback_ = false; - DispatchKeyEventPostIMECallback pending_dispatch_key_event_post_ime_callback_; - std::unique_ptr<base::RunLoop> - pending_dispatch_key_event_post_ime_callback_wait_loop_; - - DISALLOW_COPY_AND_ASSIGN(TestTextInputClient); -}; - -class InputMethodBridgeChromeOSTest : public testing::Test { - public: - InputMethodBridgeChromeOSTest() - : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {} - ~InputMethodBridgeChromeOSTest() override {} - - void SetUp() override { - ui::IMEBridge::Initialize(); - - ws::mojom::TextInputClientPtr client_ptr; - client_ = std::make_unique<TestTextInputClient>(MakeRequest(&client_ptr)); - ws::mojom::SessionDetailsPtr details = ws::mojom::SessionDetails::New(); - details->state = ws::mojom::TextInputState::New( - ui::TEXT_INPUT_TYPE_TEXT, ui::TEXT_INPUT_MODE_DEFAULT, - base::i18n::LEFT_TO_RIGHT, 0); - details->data = ws::mojom::TextInputClientData::New(); - input_method_ = std::make_unique<InputMethodBridge>( - std::make_unique<RemoteTextInputClient>(std::move(client_ptr), - std::move(details))); - } - - bool ProcessKeyEvent(std::unique_ptr<ui::Event> event) { - handled_.reset(); - - input_method_->ProcessKeyEvent( - std::move(event), - base::Bind(&InputMethodBridgeChromeOSTest::ProcessKeyEventCallback, - base::Unretained(this))); - - if (!handled_.has_value()) { - run_loop_ = std::make_unique<base::RunLoop>(); - run_loop_->Run(); - run_loop_.reset(); - } - - return handled_.value(); - } - - std::unique_ptr<ui::Event> UnicodeKeyPress(ui::KeyboardCode vkey, - ui::DomCode code, - int flags, - base::char16 character) const { - return std::make_unique<ui::KeyEvent>(ui::ET_KEY_PRESSED, vkey, code, flags, - ui::DomKey::FromCharacter(character), - ui::EventTimeForNow()); - } - - protected: - void ProcessKeyEventCallback(bool handled) { - handled_ = handled; - if (run_loop_) - run_loop_->Quit(); - } - - content::TestBrowserThreadBundle thread_bundle_; - std::unique_ptr<TestTextInputClient> client_; - std::unique_ptr<InputMethodBridge> input_method_; - std::unique_ptr<base::RunLoop> run_loop_; - base::Optional<bool> handled_; - - DISALLOW_COPY_AND_ASSIGN(InputMethodBridgeChromeOSTest); -}; - -// Tests if hexadecimal composition provided by ui::CharacterComposer works -// correctly. ui::CharacterComposer is tried if no input method extensions -// have been registered yet. -TEST_F(InputMethodBridgeChromeOSTest, HexadecimalComposition) { - struct { - ui::KeyboardCode vkey; - ui::DomCode code; - int flags; - base::char16 character; - std::string composition_text; - } kTestSequence[] = { - {ui::VKEY_U, ui::DomCode::US_U, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, - 'U', "u"}, - {ui::VKEY_3, ui::DomCode::DIGIT3, 0, '3', "u3"}, - {ui::VKEY_0, ui::DomCode::DIGIT0, 0, '0', "u30"}, - {ui::VKEY_4, ui::DomCode::DIGIT4, 0, '4', "u304"}, - {ui::VKEY_2, ui::DomCode::DIGIT2, 0, '2', "u3042"}, - }; - - // Send the Ctrl-Shift-U,3,4,0,2 sequence. - for (size_t i = 0; i < base::size(kTestSequence); i++) { - EXPECT_TRUE(ProcessKeyEvent( - UnicodeKeyPress(kTestSequence[i].vkey, kTestSequence[i].code, - kTestSequence[i].flags, kTestSequence[i].character))); - CompositionEvent ev = client_->WaitUntilCompositionEvent(); - EXPECT_EQ(CompositionEventType::SET, ev.type); - EXPECT_EQ(base::UTF8ToUTF16(kTestSequence[i].composition_text), - ev.text_data); - } - - // Press the return key and verify that the composition text was converted - // to the desired text. - EXPECT_TRUE(ProcessKeyEvent( - UnicodeKeyPress(ui::VKEY_RETURN, ui::DomCode::ENTER, 0, '\r'))); - CompositionEvent ev = client_->WaitUntilCompositionEvent(); - EXPECT_EQ(CompositionEventType::INSERT_TEXT, ev.type); - EXPECT_EQ(base::string16(1, 0x3042), ev.text_data); -} - -// Test that Ctrl-C, Ctrl-X, and Ctrl-V are not handled. -TEST_F(InputMethodBridgeChromeOSTest, ClipboardAccelerators) { - EXPECT_FALSE(ProcessKeyEvent(UnicodeKeyPress(ui::VKEY_C, ui::DomCode::US_C, - ui::EF_CONTROL_DOWN, 'C'))); - EXPECT_FALSE(ProcessKeyEvent(UnicodeKeyPress(ui::VKEY_X, ui::DomCode::US_X, - ui::EF_CONTROL_DOWN, 'X'))); - EXPECT_FALSE(ProcessKeyEvent(UnicodeKeyPress(ui::VKEY_V, ui::DomCode::US_V, - ui::EF_CONTROL_DOWN, 'V'))); -} - -// Test that multiple DispatchKeyEventPostIME calls are handled serially. -TEST_F(InputMethodBridgeChromeOSTest, SerialDispatchKeyEventPostIME) { - client_->set_manual_ack_dispatch_key_event_post_ime_callback(true); - - // Send multiple key events. - input_method_->ProcessKeyEvent( - std::make_unique<ui::KeyEvent>(ui::ET_KEY_PRESSED, ui::VKEY_A, - ui::EF_NONE), - base::DoNothing()); - input_method_->ProcessKeyEvent( - std::make_unique<ui::KeyEvent>(ui::ET_KEY_RELEASED, ui::VKEY_A, - ui::EF_NONE), - base::DoNothing()); - - // TestTextInputClient::DispatchKeyEventPostIME is called via mojo. - // RemoteTextInputClient should make the calls serially. Spin message loop to - // see whether |client_| complains about more than one call at a time. - base::RunLoop().RunUntilIdle(); - - // Ack the pending key events. - client_->AckDispatchKeyEventPostIMECallback(); - client_->AckDispatchKeyEventPostIMECallback(); -}
diff --git a/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc b/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc deleted file mode 100644 index 6ef3e425..0000000 --- a/chrome/browser/ui/views/ime_driver/remote_text_input_client.cc +++ /dev/null
@@ -1,251 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/ime_driver/remote_text_input_client.h" - -#include <memory> -#include <utility> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "ui/events/event_dispatcher.h" - -struct RemoteTextInputClient::QueuedEvent { - QueuedEvent(std::unique_ptr<ui::Event> event, - DispatchKeyEventPostIMECallback callback) - : event(std::move(event)), callback(std::move(callback)) {} - - std::unique_ptr<ui::Event> event; - DispatchKeyEventPostIMECallback callback; -}; - -RemoteTextInputClient::RemoteTextInputClient( - ws::mojom::TextInputClientPtr client, - ws::mojom::SessionDetailsPtr details) - : remote_client_(std::move(client)), details_(std::move(details)) {} - -RemoteTextInputClient::~RemoteTextInputClient() { - while (!queued_events_.empty()) { - RunNextPendingCallback(/* handled */ false, - /* stopped_propagation */ false); - } -} - -void RemoteTextInputClient::SetTextInputState( - ws::mojom::TextInputStatePtr text_input_state) { - details_->state = std::move(text_input_state); -} - -void RemoteTextInputClient::SetCaretBounds(const gfx::Rect& caret_bounds) { - details_->caret_bounds = caret_bounds; -} - -void RemoteTextInputClient::SetTextInputClientData( - ws::mojom::TextInputClientDataPtr data) { - details_->data = std::move(data); -} - -void RemoteTextInputClient::OnDispatchKeyEventPostIMECompleted( - bool handled, - bool stopped_propagation) { - RunNextPendingCallback(handled, stopped_propagation); - DispatchQueuedEvent(); -} - -void RemoteTextInputClient::SetCompositionText( - const ui::CompositionText& composition) { - remote_client_->SetCompositionText(composition); -} - -void RemoteTextInputClient::ConfirmCompositionText() { - remote_client_->ConfirmCompositionText(); -} - -void RemoteTextInputClient::ClearCompositionText() { - remote_client_->ClearCompositionText(); -} - -void RemoteTextInputClient::InsertText(const base::string16& text) { - remote_client_->InsertText(text); -} - -void RemoteTextInputClient::InsertChar(const ui::KeyEvent& event) { - remote_client_->InsertChar(ui::Event::Clone(event)); -} - -ui::TextInputType RemoteTextInputClient::GetTextInputType() const { - return details_->state->text_input_type; -} - -ui::TextInputMode RemoteTextInputClient::GetTextInputMode() const { - return details_->state->text_input_mode; -} - -base::i18n::TextDirection RemoteTextInputClient::GetTextDirection() const { - return details_->state->text_direction; -} - -int RemoteTextInputClient::GetTextInputFlags() const { - return details_->state->text_input_flags; -} - -bool RemoteTextInputClient::CanComposeInline() const { - // If we return false here, ui::InputMethodChromeOS will try to create a - // composition window. But here we are at IMEDriver, and composition - // window shouldn't be created by IMEDriver. - return true; -} - -gfx::Rect RemoteTextInputClient::GetCaretBounds() const { - return details_->caret_bounds; -} - -bool RemoteTextInputClient::GetCompositionCharacterBounds( - uint32_t index, - gfx::Rect* rect) const { - // TODO(moshayedi): crbug.com/631527. - NOTIMPLEMENTED_LOG_ONCE(); - return false; -} - -bool RemoteTextInputClient::HasCompositionText() const { - return details_->data->has_composition_text; -} - -ui::TextInputClient::FocusReason RemoteTextInputClient::GetFocusReason() const { - return details_->focus_reason; -} - -bool RemoteTextInputClient::GetTextRange(gfx::Range* range) const { - if (!details_->data->text_range.has_value()) - return false; - - *range = details_->data->text_range.value(); - return true; -} - -bool RemoteTextInputClient::GetCompositionTextRange(gfx::Range* range) const { - if (!details_->data->composition_text_range.has_value()) - return false; - - *range = details_->data->composition_text_range.value(); - return true; -} - -bool RemoteTextInputClient::GetEditableSelectionRange(gfx::Range* range) const { - if (!details_->data->editable_selection_range.has_value()) - return false; - - *range = details_->data->editable_selection_range.value(); - return true; -} - -bool RemoteTextInputClient::SetEditableSelectionRange(const gfx::Range& range) { - remote_client_->SetEditableSelectionRange(range); - // Note that we assume the client side always succeeds. - return true; -} - -bool RemoteTextInputClient::DeleteRange(const gfx::Range& range) { - remote_client_->DeleteRange(range); - // Note that we assume the client side always succeeds. - return true; -} - -bool RemoteTextInputClient::GetTextFromRange(const gfx::Range& range, - base::string16* text) const { - if (!details_->data->text.has_value() || - !details_->data->text_range.has_value() || - !details_->data->text_range->Contains(range)) { - return false; - } - - *text = details_->data->text->substr(range.GetMin(), range.length()); - return true; -} - -void RemoteTextInputClient::OnInputMethodChanged() { - remote_client_->OnInputMethodChanged(); -} - -bool RemoteTextInputClient::ChangeTextDirectionAndLayoutAlignment( - base::i18n::TextDirection direction) { - remote_client_->ChangeTextDirectionAndLayoutAlignment(direction); - // Note that we assume the client side always succeeds. - return true; -} - -void RemoteTextInputClient::ExtendSelectionAndDelete(size_t before, - size_t after) { - remote_client_->ExtendSelectionAndDelete(before, after); -} - -void RemoteTextInputClient::EnsureCaretNotInRect(const gfx::Rect& rect) { - remote_client_->EnsureCaretNotInRect(rect); -} - -bool RemoteTextInputClient::IsTextEditCommandEnabled( - ui::TextEditCommand command) const { - if (!details_->data->edit_command_enabled.has_value()) - return false; - - const size_t index = static_cast<size_t>(command); - if (index >= details_->data->edit_command_enabled->size()) - return false; - - return details_->data->edit_command_enabled->at(index); -} - -void RemoteTextInputClient::SetTextEditCommandForNextKeyEvent( - ui::TextEditCommand command) { - // TODO(moshayedi): crbug.com/631527. - NOTIMPLEMENTED_LOG_ONCE(); -} - -ukm::SourceId RemoteTextInputClient::GetClientSourceForMetrics() const { - return details_->client_source_for_metrics; -} - -bool RemoteTextInputClient::ShouldDoLearning() { - return details_->should_do_learning; -} - -bool RemoteTextInputClient::SetCompositionFromExistingText( - const gfx::Range& range, - const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) { - // TODO(https://crbug.com/952757): Implement this method. - NOTIMPLEMENTED_LOG_ONCE(); - return false; -} - -ui::EventDispatchDetails RemoteTextInputClient::DispatchKeyEventPostIME( - ui::KeyEvent* event, - DispatchKeyEventPostIMECallback callback) { - const bool is_first_event = queued_events_.empty(); - queued_events_.emplace(ui::Event::Clone(*event), std::move(callback)); - if (is_first_event) - DispatchQueuedEvent(); - return ui::EventDispatchDetails(); -} - -void RemoteTextInputClient::DispatchQueuedEvent() { - if (queued_events_.empty()) - return; - - DCHECK(queued_events_.front().event); - remote_client_->DispatchKeyEventPostIME( - std::move(queued_events_.front().event), - base::BindOnce(&RemoteTextInputClient::OnDispatchKeyEventPostIMECompleted, - weak_ptr_factory_.GetWeakPtr())); -} - -void RemoteTextInputClient::RunNextPendingCallback(bool handled, - bool stopped_propagation) { - DCHECK(!queued_events_.empty()); - DispatchKeyEventPostIMECallback callback = - std::move(queued_events_.front().callback); - queued_events_.pop(); - if (callback) - std::move(callback).Run(handled, stopped_propagation); -}
diff --git a/chrome/browser/ui/views/ime_driver/remote_text_input_client.h b/chrome/browser/ui/views/ime_driver/remote_text_input_client.h deleted file mode 100644 index c9201251..0000000 --- a/chrome/browser/ui/views/ime_driver/remote_text_input_client.h +++ /dev/null
@@ -1,103 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_VIEWS_IME_DRIVER_REMOTE_TEXT_INPUT_CLIENT_H_ -#define CHROME_BROWSER_UI_VIEWS_IME_DRIVER_REMOTE_TEXT_INPUT_CLIENT_H_ - -#include "base/containers/queue.h" -#include "base/memory/weak_ptr.h" -#include "services/ws/public/mojom/ime/ime.mojom.h" -#include "ui/base/ime/input_method_delegate.h" -#include "ui/base/ime/text_input_client.h" - -// This implementation of ui::TextInputClient sends all updates via mojo IPC to -// a remote client. This is intended to be passed to the overrides of -// ui::InputMethod::SetFocusedTextInputClient(). -// NOTE: Under SingleProcessMash this is used by ash code, for example by the -// virtual keyboard controller in //ash/keyboard/ui. -class RemoteTextInputClient : public ui::TextInputClient, - public ui::internal::InputMethodDelegate { - public: - RemoteTextInputClient(ws::mojom::TextInputClientPtr client, - ws::mojom::SessionDetailsPtr details); - ~RemoteTextInputClient() override; - - void SetTextInputState(ws::mojom::TextInputStatePtr text_input_state); - void SetCaretBounds(const gfx::Rect& caret_bounds); - void SetTextInputClientData(ws::mojom::TextInputClientDataPtr data); - - private: - struct QueuedEvent; - - // See |pending_callbacks_| for details. - void OnDispatchKeyEventPostIMECompleted(bool handled, - bool stopped_propagation); - - // ui::TextInputClient: - void SetCompositionText(const ui::CompositionText& composition) override; - void ConfirmCompositionText() override; - void ClearCompositionText() override; - void InsertText(const base::string16& text) override; - void InsertChar(const ui::KeyEvent& event) override; - ui::TextInputType GetTextInputType() const override; - ui::TextInputMode GetTextInputMode() const override; - base::i18n::TextDirection GetTextDirection() const override; - int GetTextInputFlags() const override; - bool CanComposeInline() const override; - gfx::Rect GetCaretBounds() const override; - bool GetCompositionCharacterBounds(uint32_t index, - gfx::Rect* rect) const override; - bool HasCompositionText() const override; - FocusReason GetFocusReason() const override; - bool GetTextRange(gfx::Range* range) const override; - bool GetCompositionTextRange(gfx::Range* range) const override; - bool GetEditableSelectionRange(gfx::Range* range) const override; - bool SetEditableSelectionRange(const gfx::Range& range) override; - bool DeleteRange(const gfx::Range& range) override; - bool GetTextFromRange(const gfx::Range& range, - base::string16* text) const override; - void OnInputMethodChanged() override; - bool ChangeTextDirectionAndLayoutAlignment( - base::i18n::TextDirection direction) override; - void ExtendSelectionAndDelete(size_t before, size_t after) override; - void EnsureCaretNotInRect(const gfx::Rect& rect) override; - bool IsTextEditCommandEnabled(ui::TextEditCommand command) const override; - void SetTextEditCommandForNextKeyEvent(ui::TextEditCommand command) override; - ukm::SourceId GetClientSourceForMetrics() const override; - bool ShouldDoLearning() override; - bool SetCompositionFromExistingText( - const gfx::Range& range, - const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) override; - - // ui::internal::InputMethodDelegate: - ui::EventDispatchDetails DispatchKeyEventPostIME( - ui::KeyEvent* event, - DispatchKeyEventPostIMECallback callback) override; - - // Dispatches the first queued event. - void DispatchQueuedEvent(); - - // Removes the queue event at the front of |queued_events_| and runs its - // callback with |handled| and |stopped_propagation| as arguments. - void RunNextPendingCallback(bool handled, bool stopped_propagation); - - ws::mojom::TextInputClientPtr remote_client_; - ws::mojom::SessionDetailsPtr details_; - - // Events to be dispatched with DispatchKeyEventPostIME(). Only one event is - // dispatched at a time and others are queued here until the current one - // finished processing, i.e. the response from the remote side is received - // (OnDispatchKeyEventPostIMECompleted()), the dispatched event is removed - // from the queue and its callback is invoked. This is done to avoid - // overlapping of key events processing (https://crbug.com/938808). - // Note that when we are destroyed all the callbacks needs to run. This is - // necessary as the callbacks may have originated from a remote client. - base::queue<QueuedEvent> queued_events_; - - base::WeakPtrFactory<RemoteTextInputClient> weak_ptr_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(RemoteTextInputClient); -}; - -#endif // CHROME_BROWSER_UI_VIEWS_IME_DRIVER_REMOTE_TEXT_INPUT_CLIENT_H_
diff --git a/chrome/browser/ui/views/ime_driver/simple_input_method.cc b/chrome/browser/ui/views/ime_driver/simple_input_method.cc deleted file mode 100644 index 2849773a..0000000 --- a/chrome/browser/ui/views/ime_driver/simple_input_method.cc +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/ime_driver/simple_input_method.h" - -#include <utility> - -SimpleInputMethod::SimpleInputMethod() {} - -SimpleInputMethod::~SimpleInputMethod() {} - -void SimpleInputMethod::OnTextInputStateChanged( - ws::mojom::TextInputStatePtr text_input_state) { - NOTIMPLEMENTED_LOG_ONCE(); -} - -void SimpleInputMethod::OnCaretBoundsChanged(const gfx::Rect& caret_bounds) { - NOTIMPLEMENTED_LOG_ONCE(); -} - -void SimpleInputMethod::OnTextInputClientDataChanged( - ws::mojom::TextInputClientDataPtr data) { - NOTIMPLEMENTED_LOG_ONCE(); -} - -void SimpleInputMethod::ProcessKeyEvent(std::unique_ptr<ui::Event> key_event, - ProcessKeyEventCallback callback) { - NOTIMPLEMENTED_LOG_ONCE(); - std::move(callback).Run(false); -} - -void SimpleInputMethod::CancelComposition() { - NOTIMPLEMENTED_LOG_ONCE(); -} - -void SimpleInputMethod::ShowVirtualKeyboardIfEnabled() { - NOTIMPLEMENTED_LOG_ONCE(); -}
diff --git a/chrome/browser/ui/views/ime_driver/simple_input_method.h b/chrome/browser/ui/views/ime_driver/simple_input_method.h deleted file mode 100644 index 62c9abb5..0000000 --- a/chrome/browser/ui/views/ime_driver/simple_input_method.h +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_VIEWS_IME_DRIVER_SIMPLE_INPUT_METHOD_H_ -#define CHROME_BROWSER_UI_VIEWS_IME_DRIVER_SIMPLE_INPUT_METHOD_H_ - -#include "services/ws/public/mojom/ime/ime.mojom.h" - -// This is to be used on platforms where a proper implementation of -// ws::mojom::InputMethod is missing. It doesn't handle any events and calls -// the callback with false, which will result in client code handling events -// locally. -class SimpleInputMethod : public ws::mojom::InputMethod { - public: - SimpleInputMethod(); - ~SimpleInputMethod() override; - - // ws::mojom::InputMethod: - void OnTextInputStateChanged( - ws::mojom::TextInputStatePtr text_input_state) override; - void OnCaretBoundsChanged(const gfx::Rect& caret_bounds) override; - void OnTextInputClientDataChanged( - ws::mojom::TextInputClientDataPtr data) override; - void ProcessKeyEvent(std::unique_ptr<ui::Event> key_event, - ProcessKeyEventCallback callback) override; - void CancelComposition() override; - void ShowVirtualKeyboardIfEnabled() override; - - private: - DISALLOW_COPY_AND_ASSIGN(SimpleInputMethod); -}; - -#endif // CHROME_BROWSER_UI_VIEWS_IME_DRIVER_SIMPLE_INPUT_METHOD_H_
diff --git a/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.cc b/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.cc index be97e7d5..0bf9af2 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.cc
@@ -14,7 +14,8 @@ #include "ui/views/layout/flex_layout.h" #include "ui/views/view_class_properties.h" -ToolbarIconContainerView::ToolbarIconContainerView() { +ToolbarIconContainerView::ToolbarIconContainerView(bool uses_highlight) + : uses_highlight_(uses_highlight) { auto layout_manager = std::make_unique<views::FlexLayout>(); layout_manager->SetCollapseMargins(true).SetDefaultChildMargins( gfx::Insets(0, 0, 0, GetLayoutConstant(TOOLBAR_ELEMENT_PADDING))); @@ -70,6 +71,9 @@ } void ToolbarIconContainerView::UpdateHighlight(bool highlighted) { + if (!uses_highlight_) + return; + SetBackground(highlighted ? views::CreateRoundedRectBackground( SkColorSetA(GetToolbarInkDropBaseColor(this),
diff --git a/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.h b/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.h index 2f840ef2..cb9a8b0 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.h +++ b/chrome/browser/ui/views/toolbar/toolbar_icon_container_view.h
@@ -15,7 +15,7 @@ public views::ButtonObserver, public views::ViewObserver { public: - ToolbarIconContainerView(); + explicit ToolbarIconContainerView(bool uses_highlight); ~ToolbarIconContainerView() override; // Update all the icons it contains. Override by subclass. @@ -34,7 +34,11 @@ void OnViewFocused(views::View* observed_view) override; void OnViewBlurred(views::View* observed_view) override; + bool uses_highlight() { return uses_highlight_; } + private: + friend class ToolbarPageActionIconContainerViewBrowserTest; + // views::View: void ChildPreferredSizeChanged(views::View* child) override; void ChildVisibilityChanged(views::View* child) override; @@ -48,6 +52,9 @@ // Points to the child view that is currently highlighted. views::View* highlighted_view_ = nullptr; + // Determine whether the container shows its highlight background. + const bool uses_highlight_; + DISALLOW_COPY_AND_ASSIGN(ToolbarIconContainerView); };
diff --git a/chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view.cc b/chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view.cc index 641b8e9..f84d9cd 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view.cc
@@ -4,8 +4,10 @@ #include "chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_command_controller.h" #include "chrome/browser/ui/views/autofill/payments/local_card_migration_icon_view.h" #include "chrome/browser/ui/views/autofill/payments/save_card_icon_view.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" @@ -17,15 +19,16 @@ #include "ui/views/widget/widget.h" ToolbarPageActionIconContainerView::ToolbarPageActionIconContainerView( - CommandUpdater* command_updater, Browser* browser) - : ToolbarIconContainerView(), browser_(browser) { + : ToolbarIconContainerView( + /*uses_highlight=*/!browser->profile()->IsIncognito()), + browser_(browser) { manage_passwords_icon_views_ = - new ManagePasswordsIconViews(command_updater, this); + new ManagePasswordsIconViews(browser->command_controller(), this); page_action_icons_.push_back(manage_passwords_icon_views_); local_card_migration_icon_view_ = new autofill::LocalCardMigrationIconView( - command_updater, browser, this, + browser->command_controller(), browser, this, // TODO(crbug.com/932818): The font list and the icon color may not be // what we want here. Put placeholders for now. views::style::GetFont(CONTEXT_TOOLBAR_BUTTON, @@ -33,7 +36,7 @@ page_action_icons_.push_back(local_card_migration_icon_view_); save_card_icon_view_ = new autofill::SaveCardIconView( - command_updater, browser, this, + browser->command_controller(), browser, this, // TODO(crbug.com/932818): The font list and the icon color may not be // what we want here. Put placeholders for now. views::style::GetFont(CONTEXT_TOOLBAR_BUTTON,
diff --git a/chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view.h b/chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view.h index 18a0432..0558126 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view.h +++ b/chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view.h
@@ -12,7 +12,6 @@ class AvatarToolbarButton; class Browser; -class CommandUpdater; class ManagePasswordsIconViews; namespace autofill { @@ -26,8 +25,7 @@ public PageActionIconContainer, public PageActionIconView::Delegate { public: - ToolbarPageActionIconContainerView(CommandUpdater* command_updater, - Browser* browser); + explicit ToolbarPageActionIconContainerView(Browser* browser); ~ToolbarPageActionIconContainerView() override; PageActionIconView* GetIconView(PageActionIconType icon_type);
diff --git a/chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view_browsertest.cc b/chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view_browsertest.cc new file mode 100644 index 0000000..74d1547 --- /dev/null +++ b/chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view_browsertest.cc
@@ -0,0 +1,101 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/macros.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/toolbar/toolbar_page_action_icon_container_view.h" +#include "chrome/browser/ui/views/toolbar/toolbar_view.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/testing_profile.h" +#include "components/autofill/core/common/autofill_payments_features.h" + +// TODO(crbug.com/932818): Clean this and the same code in ukm_browsertest. +// Maybe move them to InProcessBrowserTest. +namespace { + +void UnblockOnProfileCreation(base::RunLoop* run_loop, + Profile* profile, + Profile::CreateStatus status) { + if (status == Profile::CREATE_STATUS_INITIALIZED) + run_loop->Quit(); +} + +Profile* CreateGuestProfile() { + ProfileManager* profile_manager = g_browser_process->profile_manager(); + base::FilePath new_path = profile_manager->GetGuestProfilePath(); + base::RunLoop run_loop; + profile_manager->CreateProfileAsync( + new_path, base::BindRepeating(&UnblockOnProfileCreation, &run_loop), + base::string16(), std::string()); + run_loop.Run(); + return profile_manager->GetProfileByPath(new_path); +} + +} // namespace + +// The param is whether to use the highlight in the container. +class ToolbarPageActionIconContainerViewBrowserTest + : public InProcessBrowserTest { + public: + ToolbarPageActionIconContainerViewBrowserTest() {} + ~ToolbarPageActionIconContainerViewBrowserTest() override = default; + + void SetUp() override { + scoped_feature_list_.InitAndEnableFeature( + autofill::features::kAutofillEnableToolbarStatusChip); + InProcessBrowserTest::SetUp(); + } + + void TestUsesHighlight(ToolbarPageActionIconContainerView* view, + bool expect_highlight) { + DCHECK(view); + EXPECT_EQ(view->uses_highlight(), expect_highlight); + EXPECT_EQ(view->background(), nullptr); + + view->UpdateHighlight(true); + EXPECT_EQ(view->background() != nullptr, expect_highlight); + + view->UpdateHighlight(false); + EXPECT_EQ(view->background(), nullptr); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; + + DISALLOW_COPY_AND_ASSIGN(ToolbarPageActionIconContainerViewBrowserTest); +}; + +IN_PROC_BROWSER_TEST_F(ToolbarPageActionIconContainerViewBrowserTest, + ShouldUpdateHighlightInNormalWindow) { + ToolbarPageActionIconContainerView* container_view = + BrowserView::GetBrowserViewForBrowser(browser()) + ->toolbar() + ->toolbar_page_action_container(); + TestUsesHighlight(container_view, /*expect_highlight=*/true); +} + +IN_PROC_BROWSER_TEST_F(ToolbarPageActionIconContainerViewBrowserTest, + ShouldUpdateHighlightInGuestWindow) { + Profile* guest_profile = CreateGuestProfile(); + Browser* guest_browser = CreateIncognitoBrowser(guest_profile); + ASSERT_TRUE(guest_browser->profile()->IsGuestSession()); + ToolbarPageActionIconContainerView* container_view = + BrowserView::GetBrowserViewForBrowser(guest_browser) + ->toolbar() + ->toolbar_page_action_container(); + TestUsesHighlight(container_view, /*expect_highlight=*/true); +} + +IN_PROC_BROWSER_TEST_F(ToolbarPageActionIconContainerViewBrowserTest, + ShouldNotUpdateHighlightInIncognitoWindow) { + Browser* incognito_browser = CreateIncognitoBrowser(); + ToolbarPageActionIconContainerView* container_view = + BrowserView::GetBrowserViewForBrowser(incognito_browser) + ->toolbar() + ->toolbar_page_action_container(); + TestUsesHighlight(container_view, /*expect_highlight=*/false); +}
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc index d69fb5b..e198219 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -244,8 +244,7 @@ // should not be created twice. show_avatar_toolbar_button = false; toolbar_page_action_container = - std::make_unique<ToolbarPageActionIconContainerView>( - browser_->command_controller(), browser_); + std::make_unique<ToolbarPageActionIconContainerView>(browser_); } else { #if defined(OS_CHROMEOS) // ChromeOS only badges Incognito and Guest icons in the browser window.
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc index dac4a1c..218e5bb7 100644 --- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
@@ -353,6 +353,9 @@ "cancelPrinterSetUp", base::BindRepeating(&CupsPrintersHandler::HandleSetUpCancel, base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "getEulaUrl", base::BindRepeating(&CupsPrintersHandler::HandleGetEulaUrl, + base::Unretained(this))); } void CupsPrintersHandler::OnJavascriptAllowed() { @@ -1095,6 +1098,21 @@ ResolveJavascriptCallback(base::Value(callback_id), info); } +void CupsPrintersHandler::HandleGetEulaUrl(const base::ListValue* args) { + std::string callback_id; + std::string ppdManufacturer; + std::string ppdModel; + CHECK_EQ(3U, args->GetSize()); + CHECK(args->GetString(0, &callback_id)); + CHECK(args->GetString(1, &ppdManufacturer)); + CHECK(args->GetString(2, &ppdModel)); + + // TODO(crbug/958272): Implement this function to check if a |ppdModel| has an + // EULA. + ResolveJavascriptCallback(base::Value(callback_id), + base::Value("" /* eulaUrl */)); +} + void CupsPrintersHandler::FireManuallyAddDiscoveredPrinter( const Printer& printer) { FireWebUIListener("on-manually-add-discovered-printer",
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h index 429e9a0..f790bfc 100644 --- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h +++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
@@ -176,6 +176,9 @@ void OnPrintersChanged(PrinterClass printer_class, const std::vector<Printer>& printers) override; + // Handles getting the EULA URL if available. + void HandleGetEulaUrl(const base::ListValue* args); + // ui::SelectFileDialog::Listener override: void FileSelected(const base::FilePath& path, int index,
diff --git a/chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.cc b/chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.cc index 16074ee8..de13b59 100644 --- a/chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.cc
@@ -44,6 +44,11 @@ base::BindRepeating(&KerberosAccountsHandler::HandleAddKerberosAccount, weak_factory_.GetWeakPtr())); web_ui()->RegisterMessageCallback( + "reauthenticateKerberosAccount", + base::BindRepeating( + &KerberosAccountsHandler::HandleReauthenticateKerberosAccount, + weak_factory_.GetWeakPtr())); + web_ui()->RegisterMessageCallback( "removeKerberosAccount", base::BindRepeating(&KerberosAccountsHandler::HandleRemoveKerberosAccount, weak_factory_.GetWeakPtr())); @@ -95,28 +100,23 @@ // - Prevent account changes when Kerberos is disabled. // - Remove all accounts when Kerberos is disabled. - CHECK_EQ(3U, args->GetSize()); + // TODO(ljusten): Call KerberosAddAccountDialog::Show() instead when that's + // implemented. - std::string callback_id; - CHECK(args->GetString(0, &callback_id)); - - std::string principal_name; - CHECK(args->GetString(1, &principal_name)); - - std::string password; - CHECK(args->GetString(2, &password)); - + static int count = 0; KerberosCredentialsManager::Get().AddAccountAndAuthenticate( - std::move(principal_name), password, - base::BindOnce(&KerberosAccountsHandler::OnAddAccountAndAuthenticate, - weak_factory_.GetWeakPtr(), callback_id)); + base::StringPrintf("user%i@realm", ++count), "password", + EmptyResultCallback()); } -void KerberosAccountsHandler::OnAddAccountAndAuthenticate( - const std::string& callback_id, - kerberos::ErrorType error) { - ResolveJavascriptCallback(base::Value(callback_id), - base::Value(static_cast<int>(error))); +void KerberosAccountsHandler::HandleReauthenticateKerberosAccount( + const base::ListValue* args) { + AllowJavascript(); + + CHECK(!args->GetList().empty()); + + // TODO(ljusten): Add KerberosAddAccountDialog::Show(principal_name) when + // that's implemented. } void KerberosAccountsHandler::HandleRemoveKerberosAccount(
diff --git a/chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.h b/chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.h index c15457f..16316ac 100644 --- a/chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.h +++ b/chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.h
@@ -44,14 +44,13 @@ // WebUI "addKerberosAccount" message callback. void HandleAddKerberosAccount(const base::ListValue* args); - // Callback for the credential manager's AddAccountAndAuthenticate method. - void OnAddAccountAndAuthenticate(const std::string& callback_id, - kerberos::ErrorType error); + // WebUI "reauthenticateKerberosAccount" message callback. + void HandleReauthenticateKerberosAccount(const base::ListValue* args); // WebUI "removeKerberosAccount" message callback. void HandleRemoveKerberosAccount(const base::ListValue* args); - // Callback for the credential manager's ListAccounts method. + // Callback for the Kerberos daemon's ListAccounts D-Bus method. void OnListAccounts(base::Value callback_id, const kerberos::ListAccountsResponse& response);
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc index 51c3984..387fac0 100644 --- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -1699,11 +1699,6 @@ {"kerberosAccountsSignedOut", IDS_SETTINGS_KERBEROS_ACCOUNTS_SIGNED_OUT}, {"kerberosAccountsReauthenticationLabel", IDS_SETTINGS_KERBEROS_ACCOUNTS_REAUTHENTICATION_LABEL}, - {"addKerberosAccount", IDS_SETTINGS_ADD_KERBEROS_ACCOUNT}, - {"kerberosUsername", IDS_SETTINGS_KERBEROS_USERNAME}, - {"kerberosPassword", IDS_SETTINGS_KERBEROS_PASSWORD}, - {"kerberosGeneralErrorMessage", - IDS_SETTINGS_KERBEROS_GENERAL_ERROR_MESSAGE}, {"lockScreenAddFingerprint", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_ADD_FINGERPRINT_BUTTON}, {"lockScreenChangePinButton", @@ -2083,6 +2078,7 @@ {"editPrinterButtonText", IDS_SETTINGS_PRINTING_CUPS_EDIT_PRINTER_BUTTON}, {"currentPpdMessage", IDS_SETTINGS_PRINTING_CUPS_EDIT_PRINTER_CURRENT_PPD_MESSAGE}, + {"printerEulaNotice", IDS_SETTINGS_PRINTING_CUPS_EULA_NOTICE}, #else {"localPrintersTitle", IDS_SETTINGS_PRINTING_LOCAL_PRINTERS_TITLE}, #endif
diff --git a/chrome/browser/ui/webui/welcome/nux/constants.cc b/chrome/browser/ui/webui/welcome/nux/constants.cc index 73a31c2..ac31489 100644 --- a/chrome/browser/ui/webui/welcome/nux/constants.cc +++ b/chrome/browser/ui/webui/welcome/nux/constants.cc
@@ -24,4 +24,7 @@ &kNuxOnboardingFeature, "returning-user-modules", kDefaultReturningUserModules}; +const base::FeatureParam<bool> kNuxOnboardingShowGoogleApp{ + &kNuxOnboardingFeature, "app-variation-enabled", false}; + } // namespace nux
diff --git a/chrome/browser/ui/webui/welcome/nux/constants.h b/chrome/browser/ui/webui/welcome/nux/constants.h index b57b0dd..de397b2 100644 --- a/chrome/browser/ui/webui/welcome/nux/constants.h +++ b/chrome/browser/ui/webui/welcome/nux/constants.h
@@ -21,6 +21,7 @@ extern const base::FeatureParam<std::string> kNuxOnboardingNewUserModules; extern const base::FeatureParam<std::string> kNuxOnboardingReturningUserModules; +extern const base::FeatureParam<bool> kNuxOnboardingShowGoogleApp; } // namespace nux
diff --git a/chrome/browser/ui/webui/welcome/nux/google_apps_handler.cc b/chrome/browser/ui/webui/welcome/nux/google_apps_handler.cc index e41da8b..3669d984 100644 --- a/chrome/browser/ui/webui/welcome/nux/google_apps_handler.cc +++ b/chrome/browser/ui/webui/welcome/nux/google_apps_handler.cc
@@ -11,6 +11,8 @@ #include "chrome/browser/favicon/favicon_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/welcome/nux/bookmark_item.h" +#include "chrome/browser/ui/webui/welcome/nux_helper.h" +#include "chrome/grit/chrome_unscaled_resources.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/onboarding_welcome_resources.h" #include "components/favicon/core/favicon_service.h" @@ -33,6 +35,7 @@ kTranslate = 3, kNews = 4, kChromeWebStoreDoNotUse = 5, // Deprecated. + kSearch = 6, kCount, }; @@ -41,32 +44,52 @@ constexpr const int kGoogleAppIconSize = 48; // Pixels. -GoogleAppsHandler::GoogleAppsHandler() - : // Do not translate icon name as it is not human visible and needs to - // match CSS. - google_apps_{{ - {static_cast<int>(GoogleApps::kGmail), - l10n_util::GetStringUTF8(IDS_ONBOARDING_WELCOME_NUX_GOOGLE_GMAIL), - "gmail", "https://accounts.google.com/b/0/AddMailService", - IDR_NUX_GOOGLE_APPS_GMAIL_1X}, - {static_cast<int>(GoogleApps::kYouTube), - l10n_util::GetStringUTF8( - IDS_ONBOARDING_WELCOME_NUX_GOOGLE_APPS_YOUTUBE), - "youtube", "https://youtube.com", IDR_NUX_GOOGLE_APPS_YOUTUBE_1X}, - {static_cast<int>(GoogleApps::kMaps), - l10n_util::GetStringUTF8( - IDS_ONBOARDING_WELCOME_NUX_GOOGLE_APPS_MAPS), - "maps", "https://maps.google.com", IDR_NUX_GOOGLE_APPS_MAPS_1X}, - {static_cast<int>(GoogleApps::kNews), - l10n_util::GetStringUTF8( - IDS_ONBOARDING_WELCOME_NUX_GOOGLE_APPS_NEWS), - "news", "https://news.google.com", IDR_NUX_GOOGLE_APPS_NEWS_1X}, - {static_cast<int>(GoogleApps::kTranslate), - l10n_util::GetStringUTF8( - IDS_ONBOARDING_WELCOME_NUX_GOOGLE_APPS_TRANSLATE), - "translate", "https://translate.google.com", - IDR_NUX_GOOGLE_APPS_TRANSLATE_1X}, - }} {} +GoogleAppsHandler::GoogleAppsHandler() { + // Do not translate icon name as it is not human visible and needs to + // match CSS. + + BookmarkItem gmail = { + static_cast<int>(GoogleApps::kGmail), + l10n_util::GetStringUTF8(IDS_ONBOARDING_WELCOME_NUX_GOOGLE_GMAIL), + "gmail", "https://accounts.google.com/b/0/AddMailService", + IDR_NUX_GOOGLE_APPS_GMAIL_1X}; + + if (IsAppVariationEnabled()) { +#if defined(GOOGLE_CHROME_BUILD) + google_apps_.push_back( + {static_cast<int>(GoogleApps::kSearch), + l10n_util::GetStringUTF8(IDS_ONBOARDING_WELCOME_NUX_GOOGLE_SEARCH), + "search", "https://google.com", IDS_ONBOARDING_WELCOME_SEARCH}); +#endif // GOOGLE_CHROME_BUILD + } else { + google_apps_.push_back(gmail); + } + + google_apps_.push_back( + {static_cast<int>(GoogleApps::kYouTube), + l10n_util::GetStringUTF8(IDS_ONBOARDING_WELCOME_NUX_GOOGLE_APPS_YOUTUBE), + "youtube", "https://youtube.com", IDR_NUX_GOOGLE_APPS_YOUTUBE_1X}); + + google_apps_.push_back( + {static_cast<int>(GoogleApps::kMaps), + l10n_util::GetStringUTF8(IDS_ONBOARDING_WELCOME_NUX_GOOGLE_APPS_MAPS), + "maps", "https://maps.google.com", IDR_NUX_GOOGLE_APPS_MAPS_1X}); + + if (IsAppVariationEnabled()) { + google_apps_.push_back(gmail); + } else { + google_apps_.push_back( + {static_cast<int>(GoogleApps::kNews), + l10n_util::GetStringUTF8(IDS_ONBOARDING_WELCOME_NUX_GOOGLE_APPS_NEWS), + "news", "https://news.google.com", IDR_NUX_GOOGLE_APPS_NEWS_1X}); + } + + google_apps_.push_back({static_cast<int>(GoogleApps::kTranslate), + l10n_util::GetStringUTF8( + IDS_ONBOARDING_WELCOME_NUX_GOOGLE_APPS_TRANSLATE), + "translate", "https://translate.google.com", + IDR_NUX_GOOGLE_APPS_TRANSLATE_1X}); +} GoogleAppsHandler::~GoogleAppsHandler() {} @@ -87,9 +110,9 @@ args->GetInteger(0, &appId); const BookmarkItem* selectedApp = NULL; - for (size_t i = 0; i < kGoogleAppCount; i++) { - if (google_apps_[i].id == appId) { - selectedApp = &google_apps_[i]; + for (const auto& google_app : google_apps_) { + if (google_app.id == appId) { + selectedApp = &google_app; break; } } @@ -115,7 +138,7 @@ CHECK(args->Get(0, &callback_id)); ResolveJavascriptCallback( *callback_id, - BookmarkItemsToListValue(google_apps_.data(), kGoogleAppCount)); + BookmarkItemsToListValue(google_apps_.data(), google_apps_.size())); } } // namespace nux
diff --git a/chrome/browser/ui/webui/welcome/nux/google_apps_handler.h b/chrome/browser/ui/webui/welcome/nux/google_apps_handler.h index a3db532..f35e22d4 100644 --- a/chrome/browser/ui/webui/welcome/nux/google_apps_handler.h +++ b/chrome/browser/ui/webui/welcome/nux/google_apps_handler.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_UI_WEBUI_WELCOME_NUX_GOOGLE_APPS_HANDLER_H_ #define CHROME_BROWSER_UI_WEBUI_WELCOME_NUX_GOOGLE_APPS_HANDLER_H_ -#include <array> +#include <vector> #include "base/macros.h" #include "base/values.h" @@ -25,8 +25,6 @@ kCount, }; -const size_t kGoogleAppCount = 5; - class GoogleAppsHandler : public content::WebUIMessageHandler { public: GoogleAppsHandler(); @@ -40,7 +38,7 @@ void HandleGetGoogleAppsList(const base::ListValue* args); private: - std::array<BookmarkItem, kGoogleAppCount> google_apps_; + std::vector<BookmarkItem> google_apps_; DISALLOW_COPY_AND_ASSIGN(GoogleAppsHandler); };
diff --git a/chrome/browser/ui/webui/welcome/nux_helper.cc b/chrome/browser/ui/webui/welcome/nux_helper.cc index bc2be7f..b900cc5 100644 --- a/chrome/browser/ui/webui/welcome/nux_helper.cc +++ b/chrome/browser/ui/webui/welcome/nux_helper.cc
@@ -114,6 +114,8 @@ kNuxOnboardingForceEnabledReturningUserModules = { &kNuxOnboardingForceEnabled, "returning-user-modules", "nux-set-as-default"}; +const base::FeatureParam<bool> kNuxOnboardingForceEnabledShowGoogleApp = { + &kNuxOnboardingForceEnabled, "app-variation-enabled", false}; // Onboarding experiments depend on Google being the default search provider. bool CanExperimentWithVariations(Profile* profile) { @@ -183,6 +185,11 @@ return false; } +bool IsAppVariationEnabled() { + return kNuxOnboardingForceEnabledShowGoogleApp.Get() || + kNuxOnboardingShowGoogleApp.Get(); +} + const policy::PolicyMap& GetPoliciesFromProfile(Profile* profile) { policy::ProfilePolicyConnector* profile_connector = profile->GetProfilePolicyConnector();
diff --git a/chrome/browser/ui/webui/welcome/nux_helper.h b/chrome/browser/ui/webui/welcome/nux_helper.h index 0acfe76..719d11e 100644 --- a/chrome/browser/ui/webui/welcome/nux_helper.h +++ b/chrome/browser/ui/webui/welcome/nux_helper.h
@@ -40,6 +40,8 @@ bool IsNuxOnboardingEnabled(Profile* profile); +bool IsAppVariationEnabled(); + bool DoesOnboardingHaveModulesToShow(Profile* profile); base::DictionaryValue GetNuxOnboardingModules(Profile* profile);
diff --git a/chrome/common/extensions/api/autotest_private.idl b/chrome/common/extensions/api/autotest_private.idl index 856f6600..69c6a85 100644 --- a/chrome/common/extensions/api/autotest_private.idl +++ b/chrome/common/extensions/api/autotest_private.idl
@@ -159,9 +159,6 @@ callback TakeScreenshotCallback = void (DOMString base64Png); - callback EnsureWindowServiceClientHasDrawnWindowCallback = - void(boolean success); - callback GetPrimaryDisplayScaleFactorCallback = void (double scaleFactor); callback IsTabletModeEnabledCallback = void (boolean enabled); @@ -338,15 +335,6 @@ static void setCrostiniAppScaled(DOMString appId, boolean scaled, VoidCallback callback); - // Ensure that the Window Service client identified by |clientName| has - // drawn any window. |callback| is invoked with true if the client has drawn - // anything or when it does so before the time out. Otherwise, an error - // is raised when timeout happens. - static void ensureWindowServiceClientHasDrawnWindow( - DOMString clientName, - long timeout_ms, - EnsureWindowServiceClientHasDrawnWindowCallback callback); - // Get the primary display scale factor. // |callback| is invoked with the scale factor. static void getPrimaryDisplayScaleFactor(
diff --git a/chrome/common/extensions/api/input_method_private.json b/chrome/common/extensions/api/input_method_private.json index b960ff1e..4d4cc4a 100644 --- a/chrome/common/extensions/api/input_method_private.json +++ b/chrome/common/extensions/api/input_method_private.json
@@ -34,6 +34,12 @@ } }, { + "id": "UnderlineStyle", + "type": "string", + "description": "The type of the underline to modify a composition segment.", + "enum": ["underline"] + }, + { "id": "FocusReason", "type": "string", "description": "Describes how the text field was focused", @@ -393,6 +399,64 @@ "parameters": [] } ] + }, { + "name": "setCompositionRange", + "type": "function", + "description": "Set the composition range. If this extension does not own the active IME, this fails.", + "parameters": [ + { + "name": "parameters", + "type": "object", + "properties": { + "contextID": { + "description": "ID of the context where the composition text will be set", + "type": "integer" + }, + "selectionBefore": { + "description": "How much before the current selection to set as composition.", + "type": "integer" + }, + "selectionAfter": { + "description": "How much after the current selection to set as composition.", + "type": "integer" + }, + "segments": { + "description": "List of segments and their associated types.", + "type": "array", + "optional": true, + "items": { + "type": "object", + "properties": { + "start": { + "description": "Index of the character to start this segment at", + "type": "integer" + }, + "end": { + "description": "Index of the character to end this segment after.", + "type": "integer" + }, + "style": { + "$ref": "UnderlineStyle", + "description": "The type of the underline to modify this segment." + } + } + } + } + } + }, + { + "type": "function", + "name": "callback", + "optional": true, + "description": "Called when the operation completes with a boolean indicating if the text was accepted or not. On failure, chrome.runtime.lastError is set.", + "parameters": [ + { + "name": "success", + "type": "boolean" + } + ] + } + ] } ], "events": [
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 986fc8ef7..c0f35e61 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1732,6 +1732,7 @@ "../browser/ui/views/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc", "../browser/ui/views/relaunch_notification/relaunch_recommended_bubble_view_browsertest.cc", "../browser/ui/views/relaunch_notification/relaunch_required_dialog_view_browsertest.cc", + "../browser/ui/views/toolbar/toolbar_page_action_icon_container_view_browsertest.cc", ] } deps += [ @@ -4706,9 +4707,6 @@ if (is_mac) { sources += [ "../browser/ui/views/frame/browser_non_client_frame_view_mac_unittest.mm" ] } - if (is_chromeos) { - sources += [ "../browser/ui/views/ime_driver/input_method_bridge_chromeos_unittest.cc" ] - } if (!is_chromeos) { sources += [ "../browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc",
diff --git a/chrome/test/data/extensions/api_test/input_method/typing/background.js b/chrome/test/data/extensions/api_test/input_method/typing/background.js new file mode 100644 index 0000000..24ba7db --- /dev/null +++ b/chrome/test/data/extensions/api_test/input_method/typing/background.js
@@ -0,0 +1,139 @@ +// Copyright 2019 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. + +class TestEnv { + constructor() { + this.inputContext = null; + + chrome.input.ime.onFocus.addListener((context) => { + this.inputContext = context; + }); + + chrome.input.ime.onBlur.addListener(() => { + this.inputContext = null; + }); + } + + getContextID() { + return this.inputContext.contextID; + } + + onSurroundingTextChanged() { + return new Promise((resolve) => { + chrome.input.ime.onSurroundingTextChanged.addListener( + function listener(_, surroundingInfo) { + chrome.input.ime.onSurroundingTextChanged.removeListener(listener); + resolve(surroundingInfo.text); + }); + }); + } + + onCompositionBoundsChanged() { + return new Promise((resolve) => { + chrome.inputMethodPrivate.onCompositionBoundsChanged.addListener( + function listener(_, boundsList) { + chrome.inputMethodPrivate.onCompositionBoundsChanged.removeListener( + listener); + resolve(boundsList); + }); + }); + } +}; + +const testEnv = new TestEnv(); + +// Wrap inputMethodPrivate in a promise-based API to simplify test code. +function wrapAsync(apiFunction) { + return (...args) => { + return new Promise((resolve, reject) => { + apiFunction(...args, (...result) => { + if (!!chrome.runtime.lastError) { + console.log(chrome.runtime.lastError.message); + reject(Error(chrome.runtime.lastError)); + } else { + resolve(...result); + } + }); + }); + } +} + +const asyncInputIme = { + commitText: wrapAsync(chrome.input.ime.commitText), + setComposition: wrapAsync(chrome.input.ime.setComposition), +} + +const asyncInputMethodPrivate = { + setCurrentInputMethod: + wrapAsync(chrome.inputMethodPrivate.setCurrentInputMethod), + setCompositionRange: + wrapAsync(chrome.inputMethodPrivate.setCompositionRange) +}; + +chrome.test.runTests([ + async function setUp() { + await asyncInputMethodPrivate.setCurrentInputMethod( + '_ext_ime_ilanclmaeigfpnmdlgelmhkpkegdioiptest'); + + chrome.test.succeed(); + }, + + async function setCompositionRangeTest() { + await asyncInputIme.commitText({ + contextID: testEnv.getContextID(), + text: 'hello world' + }); + + chrome.test.assertEq('hello world', + await testEnv.onSurroundingTextChanged()); + + // Cursor is at the end of the string. + await asyncInputMethodPrivate.setCompositionRange({ + contextID: testEnv.getContextID(), + selectionBefore: 5, + selectionAfter: 0, + segments: [ + { start: 0, end: 2, style: "underline" }, + { start: 2, end: 5, style: "underline" } + ] + }); + + // Should underline "world". + chrome.test.assertEq(5, + (await testEnv.onCompositionBoundsChanged()).length); + + await asyncInputIme.setComposition({ + contextID: testEnv.getContextID(), + text: "foo", + cursor: 0 + }); + + // Composition should change to "foo". + chrome.test.assertEq(3, + (await testEnv.onCompositionBoundsChanged()).length); + + // Should replace composition with "again". + await asyncInputIme.commitText({ + contextID: testEnv.getContextID(), + text: 'again' + }); + + chrome.test.assertEq('hello again', + await testEnv.onSurroundingTextChanged()); + + // Cursor is at end of the string. + // Call setCompositionRange with no segments. + await asyncInputMethodPrivate.setCompositionRange({ + contextID: testEnv.getContextID(), + selectionBefore: 5, + selectionAfter: 0 + }); + + // Composition should be "again". + chrome.test.assertEq(5, + (await testEnv.onCompositionBoundsChanged()).length); + + chrome.test.succeed(); + } +]);
diff --git a/chrome/test/data/extensions/api_test/input_method/typing/manifest.json b/chrome/test/data/extensions/api_test/input_method/typing/manifest.json new file mode 100644 index 0000000..8fdea462 --- /dev/null +++ b/chrome/test/data/extensions/api_test/input_method/typing/manifest.json
@@ -0,0 +1,20 @@ +{ + "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9fDu8apG3Dz72XTT3Ym1SfGt06tdowTlYQ+3lGlCbVpfnMOmewgRgYxzUtUPso9aQERZcmI2+7UtbWjtk6/usl9Hr7a1JBQwfaUoUygEe56ajUeZhe/ErkH5CXT84U0pokfPr5vMvc7RVPduU+UBiF0DnGb/hSpzz/1UhJ5H9AwIDAQAB", + "name": "inputMethodPrivate tests", + "version": "0.1", + "manifest_version": 2, + "description": "Input method API tests.", + "background": { + "scripts": ["background.js"] + }, + "permissions": [ "input", "inputMethodPrivate" ], + "input_components": [{ + "name": "Test IME", + "type": "ime", + "id": "test", + "description": "Test", + "language": "en", + "layouts": ["us::eng"] + }] +} +
diff --git a/chrome/test/data/extensions/api_test/input_method/typing/test_page.html b/chrome/test/data/extensions/api_test/input_method/typing/test_page.html new file mode 100644 index 0000000..cc27846 --- /dev/null +++ b/chrome/test/data/extensions/api_test/input_method/typing/test_page.html
@@ -0,0 +1,6 @@ +<!-- + * Copyright 2019 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. +--> +<input id="target" type="text" autofocus/>
diff --git a/chrome/test/data/webui/print_preview/destination_select_test.js b/chrome/test/data/webui/print_preview/destination_select_test.js index ad8090d..9f056d8 100644 --- a/chrome/test/data/webui/print_preview/destination_select_test.js +++ b/chrome/test/data/webui/print_preview/destination_select_test.js
@@ -91,9 +91,10 @@ JSON.parse(initialSettings.serializedAppStateStr).recentDestinations : []; destinationSettings.setSetting('recentDestinations', recentDestinations); - destinationSettings.initDestinationStore( + destinationSettings.init( initialSettings.printerName, - initialSettings.serializedDefaultDestinationSelectionRulesStr); + initialSettings.serializedDefaultDestinationSelectionRulesStr, + initialSettings.userAccounts); destinationSettings.disabled = false; return opt_expectPrinterFailure ? Promise.resolve() : Promise.race([ nativeLayer.whenCalled('getPrinterCapabilities'), whenCapabilitiesReady @@ -337,6 +338,7 @@ version: 2, recentDestinations: [recentDestination], }); + initialSettings.userAccounts = ['foo@chromium.org']; return setInitialSettings().then(function(args) { assertEquals('FooDevice', args.destinationId); @@ -400,6 +402,7 @@ version: 2, recentDestinations: recentDestinations, }); + initialSettings.userAccounts = [account1, account2]; return setInitialSettings() .then(() => {
diff --git a/chrome/test/data/webui/print_preview/destination_settings_test.js b/chrome/test/data/webui/print_preview/destination_settings_test.js index d46ae79..1229f78 100644 --- a/chrome/test/data/webui/print_preview/destination_settings_test.js +++ b/chrome/test/data/webui/print_preview/destination_settings_test.js
@@ -35,6 +35,9 @@ /** @type {!Array<!print_preview.Destination>} */ let destinations = []; + /** @type {!Array<string>} */ + let initialAccounts = []; + /** @type {string} */ const defaultUser = 'foo@chromium.org'; @@ -78,9 +81,10 @@ // Set up the destination store, but no destination yet. Dropdown is still // hidden. - destinationSettings.initDestinationStore( + destinationSettings.init( 'FooDevice' /* printerName */, - '' /* serializedDefaultDestinationSelectionRulesStr */); + '' /* serializedDefaultDestinationSelectionRulesStr */, + [] /* userAccounts */); assertTrue(dropdown.hidden); return test_util @@ -161,15 +165,18 @@ destinationSettings.cloudPrintInterface = cloudPrintInterface; destinationSettings.setSetting('recentDestinations', recentDestinations); destinationSettings.appKioskMode = false; - destinationSettings.initDestinationStore( + destinationSettings.init( '' /* printerName */, - '' /* serializedDefaultDestinationSelectionRulesStr */); + '' /* serializedDefaultDestinationSelectionRulesStr */, + initialAccounts); destinationSettings.state = print_preview.State.READY; destinationSettings.disabled = false; } /** Simulates a user signing in to Chrome. */ function signIn() { + destinationSettings.$.userInfo.updateActiveUser(defaultUser, false); + destinationSettings.$.userInfo.updateUsers([defaultUser]); cloudPrintInterface.setPrinter( print_preview_test_utils.getGoogleDriveDestination(defaultUser)); cr.webUIListenerCallback('reload-printer-list'); @@ -533,6 +540,7 @@ cloudPrinterUser1, cloudPrinterUser2, destinations[0] ].map(destination => print_preview.makeRecentDestination(destination)); + initialAccounts = [defaultUser, account2]; initialize(); Polymer.dom.flush();
diff --git a/chrome/test/data/webui/print_preview/invalid_settings_browsertest.js b/chrome/test/data/webui/print_preview/invalid_settings_browsertest.js index 4a4a6c75..8d12aea 100644 --- a/chrome/test/data/webui/print_preview/invalid_settings_browsertest.js +++ b/chrome/test/data/webui/print_preview/invalid_settings_browsertest.js
@@ -97,6 +97,7 @@ ], }); initialSettings.cloudPrintURL = 'cloudprint URL'; + initialSettings.userAccounts = [printers[0].account]; localDestinationInfos = []; loadTimeData.overrideValues({isEnterpriseManaged: false});
diff --git a/chrome/test/data/webui/print_preview/pages_settings_test.js b/chrome/test/data/webui/print_preview/pages_settings_test.js index de86239..8d3770e 100644 --- a/chrome/test/data/webui/print_preview/pages_settings_test.js +++ b/chrome/test/data/webui/print_preview/pages_settings_test.js
@@ -108,6 +108,11 @@ pagesSection, pagesSection.pagesValueEnum_.CUSTOM.toString()); assertTrue(customInputCollapse.opened); validateState([1, 2], [{from: 1, to: 2}], '', false); + + // Set a selection equal to the full page range. This should set ranges to + // empty, so that reselecting "all" does not regenerate the preview. + await setCustomInput('1-3'); + validateState([1, 2, 3], [], '', false); }); // Tests that the page ranges set are valid for different user inputs. @@ -133,7 +138,7 @@ validateState(tenToHundred, [{from: 10, to: 100}], '', false); await setCustomInput('-'); - validateState(oneToHundred, [{from: 1, to: 100}], '', false); + validateState(oneToHundred, [], '', false); // https://crbug.com/806165 await setCustomInput('1\u30012\u30013\u30011\u300156'); @@ -246,18 +251,18 @@ await whenBlurred; // Blurring a blank field sets the full page range. assertEquals(customValue, select.value); - validateState([1, 2, 3], [{from: 1, to: 3}], '', false); + validateState([1, 2, 3], [], '', false); assertEquals('1-3', input.value); input.focus(); await setCustomInput('5'); assertEquals(customValue, select.value); // Invalid input doesn't change the preview. - validateState([1, 2, 3], [{from: 1, to: 3}], limitError + '3', true); + validateState([1, 2, 3], [], limitError + '3', true); await setCustomInput(''); assertEquals(customValue, select.value); - validateState([1, 2, 3], [{from: 1, to: 3}], '', false); + validateState([1, 2, 3], [], '', false); whenBlurred = test_util.eventToPromise('blur', input); input.blur(); @@ -265,7 +270,7 @@ // value to all pages. await whenBlurred; assertEquals(customValue, select.value); - validateState([1, 2, 3], [{from: 1, to: 3}], '', false); + validateState([1, 2, 3], [], '', false); assertEquals('1-3', input.value); // Re-focus and clear the input and then select "All" in the
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js index 74b8c44a..1e02026 100644 --- a/chrome/test/data/webui/settings/cr_settings_browsertest.js +++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -590,7 +590,8 @@ ]), }; -TEST_F('CrSettingsPeoplePageKerberosAccountsTest', 'All', function() { +// Test is consistently failing. http://crbug.com/960837 +TEST_F('CrSettingsPeoplePageKerberosAccountsTest', 'DISABLED_All', function() { mocha.run(); });
diff --git a/chrome/test/data/webui/settings/cups_printer_page_tests.js b/chrome/test/data/webui/settings/cups_printer_page_tests.js index f937df8..2c4aca4 100644 --- a/chrome/test/data/webui/settings/cups_printer_page_tests.js +++ b/chrome/test/data/webui/settings/cups_printer_page_tests.js
@@ -18,6 +18,7 @@ 'cancelPrinterSetUp', 'updateCupsPrinter', 'reconfigureCupsPrinter', + 'getEulaUrl', ]); this.printerList = []; @@ -25,6 +26,13 @@ this.models = []; this.printerInfo = {}; this.printerPpdMakeModel = {}; + + /** + * |eulaUrl_| in conjunction with |setEulaUrl| mimics setting the EULA url + * for a printer. + * @private {string} + */ + this.eulaUrl_ = ''; } /** @override */ @@ -78,7 +86,7 @@ /** @override */ updateCupsPrinter(printerId, printerName) { - this.methodCalled('updateCupsPrinter', printerId, printerName); + this.methodCalled('updateCupsPrinter', [printerId, printerName]); } /** @override */ @@ -91,6 +99,44 @@ reconfigureCupsPrinter(printer) { this.methodCalled('reconfigureCupsPrinter', printer); } + + /** @override */ + getEulaUrl(ppdManufacturer, ppdModel) { + this.methodCalled('getEulaUrl', [ppdManufacturer, ppdModel]); + return Promise.resolve(this.eulaUrl_); + } + + /** @param {string} eulaUrl */ + setEulaUrl(eulaUrl) { + this.eulaUrl_ = eulaUrl; + } +} + +/* + * Helper function that waits for |getEulaUrl| to get called and then verifies + * its arguments. + * @param {!TestCupsPrintersBrowserProxy} cupsPrintersBrowserProxy + * @param {string} expectedManufacturer + * @param {string} expectedModel + * @return {!Promise} + */ +function verifyGetEulaUrlWasCalled( + cupsPrintersBrowserProxy, expectedManufacturer, expectedModel) { + return cupsPrintersBrowserProxy.whenCalled('getEulaUrl').then(function(args) { + assertEquals(expectedManufacturer, args[0]); // ppdManufacturer + assertEquals(expectedModel, args[1]); // ppdModel + }); +} + +/* + * Helper function that resets the resolver for |getEulaUrl| and sets the new + * EULA URL. + * @param {!TestCupsPrintersBrowserProxy} cupsPrintersBrowserProxy + * @param {string} eulaUrl + */ +function resetGetEulaUrl(cupsPrintersBrowserProxy, eulaUrl) { + cupsPrintersBrowserProxy.resetResolver('getEulaUrl'); + cupsPrintersBrowserProxy.setEulaUrl(eulaUrl); } suite('CupsAddPrinterDialogTests', function() { @@ -481,6 +527,78 @@ assertFalse(dialog.showConfiguringDialog_); }); }); + + /** + * Test that we are checking if a printer model has an EULA upon a model + * change. + */ + test('getEulaUrlGetsCalledOnModelChange', function() { + const discoveryDialog = dialog.$$('add-printer-discovery-dialog'); + assertTrue(!!discoveryDialog); + discoveryDialog.$$('.secondary-button').click(); + Polymer.dom.flush(); + + const addDialog = dialog.$$('add-printer-manually-dialog'); + assertTrue(!!addDialog); + fillAddManuallyDialog(addDialog); + + addDialog.$$('.action-button').click(); + Polymer.dom.flush(); + + const eulaLink = 'google.com'; + const expectedManufacturer = 'Google'; + const expectedModel = 'printer'; + const expectedModel2 = 'newPrinter'; + const expectedModel3 = 'newPrinter2'; + + let modelDialog = null; + let urlElement = null; + let modelDropdown = null; + + return cupsPrintersBrowserProxy + .whenCalled('getCupsPrinterManufacturersList') + .then(function() { + modelDialog = dialog.$$('add-printer-manufacturer-model-dialog'); + assertTrue(!!modelDialog); + + urlElement = modelDialog.$$('#eulaUrl'); + // Check that the EULA text is not shown. + assertTrue(urlElement.hidden); + + cupsPrintersBrowserProxy.setEulaUrl(eulaLink); + + modelDialog.$$('#manufacturerDropdown').value = expectedManufacturer; + modelDropdown = modelDialog.$$('#modelDropdown'); + modelDropdown.value = expectedModel; + return verifyGetEulaUrlWasCalled( + cupsPrintersBrowserProxy, expectedManufacturer, expectedModel); + }) + .then(function(args) { + // Check that the EULA text is shown. + assertFalse(urlElement.hidden); + + resetGetEulaUrl(cupsPrintersBrowserProxy, '' /* eulaUrl */); + + // Change ppdModel and expect |getEulaUrl| to be called again. + modelDropdown.value = expectedModel2; + return verifyGetEulaUrlWasCalled( + cupsPrintersBrowserProxy, expectedManufacturer, expectedModel2); + }) + .then(function(args) { + // Check that the EULA text is hidden. + assertTrue(urlElement.hidden); + + resetGetEulaUrl(cupsPrintersBrowserProxy, eulaLink); + + // Change ppdModel and expect |getEulaUrl| to be called again. + modelDropdown.value = expectedModel3; + return verifyGetEulaUrlWasCalled( + cupsPrintersBrowserProxy, expectedManufacturer, expectedModel3); + }) + .then(function(args) { + assertFalse(urlElement.hidden); + }); + }); }); suite('EditPrinterDialog', function() { @@ -981,4 +1099,61 @@ Polymer.dom.flush(); assertTrue(!saveButton.disabled); }); + + /** + * Test that we are checking if a printer model has an EULA upon a model + * change. + */ + test('getEulaUrlGetsCalledOnModelChange', function() { + const eulaLink = 'google.com'; + const expectedManufacturer = 'Google'; + const expectedModel = 'model'; + const expectedModel2 = 'newModel'; + const expectedModel3 = 'newModel2'; + + let modelDropdown = null; + let urlElement = null; + + return PolymerTest.flushTasks() + .then(function() { + urlElement = dialog.$$('#eulaUrl'); + // Check that the EULA text is hidden. + assertTrue(urlElement.hidden); + + cupsPrintersBrowserProxy.setEulaUrl(eulaLink); + + dialog.$$('#printerPPDManufacturer').value = expectedManufacturer; + modelDropdown = dialog.$$('#printerPPDModel'); + modelDropdown.value = expectedModel; + + return verifyGetEulaUrlWasCalled( + cupsPrintersBrowserProxy, expectedManufacturer, expectedModel); + }) + .then(function() { + // Check that the EULA text is shown. + assertFalse(urlElement.hidden); + + resetGetEulaUrl(cupsPrintersBrowserProxy, '' /* eulaUrl */); + + // Change ppdModel and expect |getEulaUrl| to be called again. + modelDropdown.value = expectedModel2; + return verifyGetEulaUrlWasCalled( + cupsPrintersBrowserProxy, expectedManufacturer, expectedModel2); + }) + .then(function() { + // Check that the EULA text is hidden. + assertTrue(urlElement.hidden); + + resetGetEulaUrl(cupsPrintersBrowserProxy, eulaLink); + + // Change ppdModel and expect |getEulaUrl| to be called again. + modelDropdown.value = expectedModel3; + return verifyGetEulaUrlWasCalled( + cupsPrintersBrowserProxy, expectedManufacturer, expectedModel3); + }) + .then(function() { + // Check that the EULA text is shown again. + assertFalse(urlElement.hidden); + }); + }); });
diff --git a/chrome/test/data/webui/settings/people_page_kerberos_accounts_test.js b/chrome/test/data/webui/settings/people_page_kerberos_accounts_test.js index 3b06cf9..855e0a4 100644 --- a/chrome/test/data/webui/settings/people_page_kerberos_accounts_test.js +++ b/chrome/test/data/webui/settings/people_page_kerberos_accounts_test.js
@@ -9,11 +9,9 @@ super([ 'getAccounts', 'addAccount', + 'reauthenticateAccount', 'removeAccount', ]); - - // Simulated error from a addKerberosAccount call. - this.addAccountError = ErrorType.kNone; } /** @override */ @@ -35,9 +33,13 @@ } /** @override */ - addAccount(principalName, password) { - this.methodCalled('addAccount', [principalName, password]); - return Promise.resolve(this.addAccountError); + addAccount() { + this.methodCalled('addAccount'); + } + + /** @override */ + reauthenticateAccount(principalName) { + this.methodCalled('reauthenticateAccount', principalName); } /** @override */ @@ -46,7 +48,6 @@ } } - // Tests for the Kerberos Accounts settings page. suite('KerberosAccountsTests', function() { let browserProxy = null; let kerberosAccounts = null; @@ -78,34 +79,22 @@ }); test('AddAccount', function() { - assertTrue(!kerberosAccounts.$$('kerberos-add-account-dialog')); assertFalse(kerberosAccounts.$$('#add-account-button').disabled); kerberosAccounts.$$('#add-account-button').click(); - Polymer.dom.flush(); - addDialog = kerberosAccounts.$$('kerberos-add-account-dialog'); - assertTrue(!!addDialog); - assertEquals('', addDialog.username); + assertEquals(1, browserProxy.getCallCount('addAccount')); }); test('ReauthenticateAccount', function() { - // Wait until accounts are loaded. return browserProxy.whenCalled('getAccounts').then(() => { Polymer.dom.flush(); - - // The kerberos-add-account-dialog shouldn't be open yet. - assertTrue(!kerberosAccounts.$$('kerberos-add-account-dialog')); - - // Click "Sign-In" on an existing account. // Note that both accounts have a reauth button, but [0] is hidden, so // click [1] (clicking a hidden button works, but it feels weird). kerberosAccounts.root.querySelectorAll('.reauth-button')[1].click(); - Polymer.dom.flush(); - - // Now the kerberos-add-account-dialog should be open with preset - // username. - addDialog = kerberosAccounts.$$('kerberos-add-account-dialog'); - assertTrue(!!addDialog); - assertEquals('user2@REALM2', addDialog.username); + assertEquals(1, browserProxy.getCallCount('reauthenticateAccount')); + return browserProxy.whenCalled('reauthenticateAccount') + .then((principalName) => { + assertEquals('user2@REALM2', principalName); + }); }); }); @@ -129,141 +118,4 @@ assertEquals(2, browserProxy.getCallCount('getAccounts')); }); }); - - // Tests for the kerberos-add-account-dialog element. - suite('KerberosAddAccountTests', function() { - let browserProxy = null; - let dialog = null; - let username = null; - let password = null; - let addButton = null; - let generalError = null; - - setup(function() { - browserProxy = new TestKerberosAccountsBrowserProxy(); - settings.KerberosAccountsBrowserProxyImpl.instance_ = browserProxy; - PolymerTest.clearBody(); - - dialog = document.createElement('kerberos-add-account-dialog'); - document.body.appendChild(dialog); - - username = dialog.$.username; - assertTrue(!!username); - - password = dialog.$.password; - assertTrue(!!password); - - addButton = dialog.$$('.action-button'); - assertTrue(!!addButton); - - generalError = dialog.$['general-error-message']; - assertTrue(!!generalError); - }); - - teardown(function() { - dialog.remove(); - }); - - // Sets |error| as error result for addAccount(), simulates a click on the - // addAccount button and checks that |errorElement| has an non-empty - // innerText value afterwards. - function checkAddAccountError(error, errorElement) { - Polymer.dom.flush(); - assertEquals(0, errorElement.innerText.length); - browserProxy.addAccountError = error; - addButton.click(); - return browserProxy.whenCalled('addAccount').then(function() { - Polymer.dom.flush(); - assertNotEquals(0, errorElement.innerText.length); - }); - } - - // The username input field is not disabled by default. - test('UsernameFieldNotDisabledByDefault', function() { - assertFalse(username.disabled); - }); - - // The username input field is disabled if a username is preset before the - // dialog is appended to the document. - test('UsernameFieldDisabledIfPreset', function() { - const newDialog = document.createElement('kerberos-add-account-dialog'); - newDialog.username = 'user'; - document.body.appendChild(newDialog); - assertTrue(newDialog.$.username.disabled); - }); - - // By clicking the "Add account", the username and password values are - // passed to the 'addAccount' browser proxy method. - test('AddButtonPassesCredentials', function() { - const EXPECTED_USER = 'testuser'; - const EXPECTED_PASS = 'testpass'; - username.value = EXPECTED_USER; - password.value = EXPECTED_PASS; - assertFalse(addButton.disabled); - addButton.click(); - return browserProxy.whenCalled('addAccount').then(function(args) { - assertEquals(EXPECTED_USER, args[0]); - assertEquals(EXPECTED_PASS, args[1]); - }); - }); - - // While an account is being added, the "Add account" is disabled. - test('AddButtonDisableWhileInProgress', function() { - assertFalse(addButton.disabled); - addButton.click(); - assertTrue(addButton.disabled); - return browserProxy.whenCalled('addAccount').then(function(args) { - assertFalse(addButton.disabled); - }); - }); - - // addAccount: ErrorType.kNetworkProblem spawns a general error. - test('AddAccountError_NetworkProblem', function() { - checkAddAccountError( - settings.KerberosErrorType.kNetworkProblem, generalError); - }); - - // addAccount: ErrorType.kParsePrincipalFailed spawns a username error. - test('AddAccountError_ParsePrincipalFailed', function() { - checkAddAccountError( - settings.KerberosErrorType.kParsePrincipalFailed, username.$.error); - }); - - // addAccount: ErrorType.kBadPrincipal spawns a username error. - test('AddAccountError_BadPrincipal', function() { - checkAddAccountError( - settings.KerberosErrorType.kBadPrincipal, username.$.error); - }); - - // addAccount: ErrorType.kContactingKdcFailed spawns a username error. - test('AddAccountError_ContactingKdcFailed', function() { - checkAddAccountError( - settings.KerberosErrorType.kContactingKdcFailed, username.$.error); - }); - - // addAccount: ErrorType.kBadPassword spawns a password error. - test('AddAccountError_BadPassword', function() { - checkAddAccountError( - settings.KerberosErrorType.kBadPassword, password.$.error); - }); - - // addAccount: ErrorType.kPasswordExpired spawns a password error. - test('AddAccountError_PasswordExpired', function() { - checkAddAccountError( - settings.KerberosErrorType.kPasswordExpired, password.$.error); - }); - - // addAccount: ErrorType.kKdcDoesNotSupportEncryptionType spawns a general - // error. - test('AddAccountError_KdcDoesNotSupportEncryptionType', function() { - checkAddAccountError( - settings.KerberosErrorType.kKdcDoesNotSupportEncryptionType, - generalError); - }); - - // addAccount: ErrorType.kUnknown spawns a general error. - test('AddAccountError_Unknown', function() { - checkAddAccountError(settings.KerberosErrorType.kUnknown, generalError); - }); - }); -}); \ No newline at end of file +});
diff --git a/chrome/test/delayload/delayloads_unittest.cc b/chrome/test/delayload/delayloads_unittest.cc index 2d09341..ff4bfd9 100644 --- a/chrome/test/delayload/delayloads_unittest.cc +++ b/chrome/test/delayload/delayloads_unittest.cc
@@ -114,7 +114,7 @@ } } -TEST_F(DelayloadsTest, ChromeDllLoadSanityTest) { +TEST_F(DelayloadsTest, DISABLED_ChromeDllLoadSanityTest) { // As a precaution to avoid affecting other tests, we need to ensure this is // executed in its own test process. This "test" will re-launch with custom // parameters to accomplish that. @@ -159,7 +159,7 @@ EXPECT_TRUE(!!::FreeLibrary(chrome_module_handle)); } -TEST_F(DelayloadsTest, ChromeChildDllDelayloadsCheck) { +TEST_F(DelayloadsTest, DISABLED_ChromeChildDllDelayloadsCheck) { base::FilePath dll; ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &dll)); dll = dll.Append(L"chrome_child.dll");
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc index c40c561..2794eb6 100644 --- a/chrome/test/ppapi/ppapi_browsertest.cc +++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -2146,7 +2146,9 @@ // aura: http://crbug.com/104384 // cros: http://crbug.com/396502 // windows: http://crbug.com/899893 -#if defined(OS_MACOSX) || defined(OS_CHROMEOS) || defined(OS_WIN) +// linux: http://crbug.com/899893 +#if defined(OS_MACOSX) || defined(OS_CHROMEOS) || defined(OS_WIN) || \ + defined(OS_LINUX) #define MAYBE_FlashFullscreen DISABLED_FlashFullscreen #else #define MAYBE_FlashFullscreen FlashFullscreen
diff --git a/chrome/tools/build/mac/clean_up_old_versions.py b/chrome/tools/build/mac/clean_up_old_versions.py index 7c34560..c8216dc3 100644 --- a/chrome/tools/build/mac/clean_up_old_versions.py +++ b/chrome/tools/build/mac/clean_up_old_versions.py
@@ -19,6 +19,10 @@ else: os.unlink(path) + for path in args.delete: + if os.path.exists(path): + shutil.rmtree(path) + open(args.stamp, 'w').close() os.utime(args.stamp, None) @@ -32,9 +36,16 @@ parser.add_argument( '--keep', action='append', + default=[], help=('The names of items to keep in the `--versions-dir`. ' 'Can be specified multiple times.')) parser.add_argument( + '--delete', + action='append', + default=[], + help=('Unconditionally deletes the tree at this path. Can be ' + 'specified multiple times.')) + parser.add_argument( '--stamp', required=True, help='Path to write the stamp file.') args = parser.parse_args()
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn index 8e49eb1..0444371c 100644 --- a/chromecast/browser/BUILD.gn +++ b/chromecast/browser/BUILD.gn
@@ -139,6 +139,7 @@ ":prefs", ":public", "//chromecast/browser/metrics", + "//chromecast/metrics", ] deps = [
diff --git a/chromecast/browser/DEPS b/chromecast/browser/DEPS index ddc5fd9..73d6d406 100644 --- a/chromecast/browser/DEPS +++ b/chromecast/browser/DEPS
@@ -9,6 +9,7 @@ "+chromecast/external_mojo", "+chromecast/internal/shell/browser", "+chromecast/media", + "+chromecast/metrics", "+chromecast/net", "+chromecast/service", "+components/cdm/browser",
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc index ffce4483..fc0b42bc 100644 --- a/chromecast/browser/cast_browser_main_parts.cc +++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -40,7 +40,7 @@ #include "chromecast/browser/cast_net_log.h" #include "chromecast/browser/devtools/remote_debugging_server.h" #include "chromecast/browser/media/media_caps_impl.h" -#include "chromecast/browser/metrics/cast_metrics_service_client.h" +#include "chromecast/browser/metrics/cast_browser_metrics.h" #include "chromecast/browser/tts/tts_controller_impl.h" #include "chromecast/browser/tts/tts_platform_stub.h" #include "chromecast/browser/url_request_context_factory.h" @@ -50,6 +50,7 @@ #include "chromecast/media/base/media_resource_tracker.h" #include "chromecast/media/base/video_plane_controller.h" #include "chromecast/media/cma/backend/media_pipeline_backend_manager.h" +#include "chromecast/metrics/cast_metrics_service_client.h" #include "chromecast/net/connectivity_checker.h" #include "chromecast/public/cast_media_shlib.h" #include "chromecast/service/cast_service.h" @@ -613,7 +614,7 @@ // service is initialized because CastMetricsServiceClient, // CastURLLoaderThrottle and CastNetworkDelegate may use components // initialized by cast service. - cast_browser_process_->metrics_service_client()->Initialize(); + cast_browser_process_->cast_browser_metrics()->Initialize(); cast_content_browser_client_->InitializeURLLoaderThrottleDelegate(); url_request_context_factory_->InitializeNetworkDelegates(); @@ -700,7 +701,7 @@ window_manager_.reset(); cast_browser_process_->cast_service()->Finalize(); - cast_browser_process_->metrics_service_client()->Finalize(); + cast_browser_process_->cast_browser_metrics()->Finalize(); cast_browser_process_.reset(); #if !defined(OS_FUCHSIA)
diff --git a/chromecast/browser/cast_browser_process.cc b/chromecast/browser/cast_browser_process.cc index 1f127f5..541a761 100644 --- a/chromecast/browser/cast_browser_process.cc +++ b/chromecast/browser/cast_browser_process.cc
@@ -12,8 +12,9 @@ #include "chromecast/browser/cast_content_browser_client.h" #include "chromecast/browser/cast_network_contexts.h" #include "chromecast/browser/devtools/remote_debugging_server.h" -#include "chromecast/browser/metrics/cast_metrics_service_client.h" +#include "chromecast/browser/metrics/cast_browser_metrics.h" #include "chromecast/browser/tts/tts_controller.h" +#include "chromecast/metrics/cast_metrics_service_client.h" #include "chromecast/net/connectivity_checker.h" #include "chromecast/service/cast_service.h" #include "components/prefs/pref_service.h" @@ -112,8 +113,9 @@ void CastBrowserProcess::SetMetricsServiceClient( std::unique_ptr<metrics::CastMetricsServiceClient> metrics_service_client) { - DCHECK(!metrics_service_client_); - metrics_service_client_.swap(metrics_service_client); + DCHECK(!cast_browser_metrics_); + cast_browser_metrics_ = std::make_unique<metrics::CastBrowserMetrics>( + std::move(metrics_service_client)); } void CastBrowserProcess::SetPrefService(
diff --git a/chromecast/browser/cast_browser_process.h b/chromecast/browser/cast_browser_process.h index 8f0dac0..3220ec6 100644 --- a/chromecast/browser/cast_browser_process.h +++ b/chromecast/browser/cast_browser_process.h
@@ -27,6 +27,7 @@ namespace metrics { class CastMetricsServiceClient; +class CastBrowserMetrics; } // namespace metrics namespace shell { @@ -96,8 +97,8 @@ #endif // BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS) #endif // defined(USE_AURA) - metrics::CastMetricsServiceClient* metrics_service_client() const { - return metrics_service_client_.get(); + metrics::CastBrowserMetrics* cast_browser_metrics() const { + return cast_browser_metrics_.get(); } PrefService* pref_service() const { return pref_service_.get(); } ConnectivityChecker* connectivity_checker() const { @@ -125,7 +126,7 @@ std::unique_ptr<PrefService> pref_service_; scoped_refptr<ConnectivityChecker> connectivity_checker_; std::unique_ptr<CastBrowserContext> browser_context_; - std::unique_ptr<metrics::CastMetricsServiceClient> metrics_service_client_; + std::unique_ptr<metrics::CastBrowserMetrics> cast_browser_metrics_; std::unique_ptr<RemoteDebuggingServer> remote_debugging_server_; CastWebViewFactory* web_view_factory_ = nullptr;
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc index 6a0363fd..e3d96c06 100644 --- a/chromecast/browser/cast_content_browser_client.cc +++ b/chromecast/browser/cast_content_browser_client.cc
@@ -233,11 +233,15 @@ #endif }); - // TODO(mdellaquila): This feature has to be disabled because it causes - // significantly higher power consumption while flinging media files. - // Remove this after fixing the bug: b/111363899 - cast_feature_list_creator_->SetExtraDisableFeatures( - {::media::kUseModernMediaControls}); + cast_feature_list_creator_->SetExtraDisableFeatures({ + // TODO(mdellaquila): This feature has to be disabled because it causes + // significantly higher power consumption while flinging media files. + // Remove this after fixing the bug: b/111363899 + ::media::kUseModernMediaControls, +#if defined(OS_ANDROID) + ::media::kAudioFocusLossSuspendMediaSession, +#endif + }); } CastContentBrowserClient::~CastContentBrowserClient() {
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h index bd3e2f6..244b4a47 100644 --- a/chromecast/browser/cast_content_browser_client.h +++ b/chromecast/browser/cast_content_browser_client.h
@@ -15,8 +15,8 @@ #include "base/threading/thread.h" #include "build/build_config.h" #include "build/buildflag.h" -#include "chromecast/browser/metrics/cast_metrics_service_client.h" #include "chromecast/chromecast_buildflags.h" +#include "chromecast/metrics/cast_metrics_service_client.h" #include "content/public/browser/certificate_request_result_type.h" #include "content/public/browser/content_browser_client.h" #include "services/service_manager/public/cpp/binder_registry.h"
diff --git a/chromecast/browser/metrics/BUILD.gn b/chromecast/browser/metrics/BUILD.gn index 12afe05..c029745 100644 --- a/chromecast/browser/metrics/BUILD.gn +++ b/chromecast/browser/metrics/BUILD.gn
@@ -6,10 +6,10 @@ cast_source_set("metrics") { sources = [ + "cast_browser_metrics.cc", + "cast_browser_metrics.h", "cast_metrics_prefs.cc", "cast_metrics_prefs.h", - "cast_metrics_service_client.cc", - "cast_metrics_service_client.h", "cast_stability_metrics_provider.cc", "cast_stability_metrics_provider.h", ] @@ -20,6 +20,7 @@ "//chromecast/base", "//chromecast/base:cast_sys_info_util", "//chromecast/base:cast_version", + "//chromecast/metrics", "//components/metrics", "//components/metrics:gpu", "//components/metrics:net",
diff --git a/chromecast/browser/metrics/DEPS b/chromecast/browser/metrics/DEPS index ac999449..f0a2c8d 100644 --- a/chromecast/browser/metrics/DEPS +++ b/chromecast/browser/metrics/DEPS
@@ -1,4 +1,5 @@ include_rules = [ + "+chromecast/metrics", "+components/metrics", "+third_party/metrics_proto", ]
diff --git a/chromecast/browser/metrics/cast_browser_metrics.cc b/chromecast/browser/metrics/cast_browser_metrics.cc new file mode 100644 index 0000000..22b4740 --- /dev/null +++ b/chromecast/browser/metrics/cast_browser_metrics.cc
@@ -0,0 +1,139 @@ +// Copyright 2019 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 "chromecast/browser/metrics/cast_browser_metrics.h" + +#include "base/bind.h" +#include "base/command_line.h" +#include "base/logging.h" +#include "base/threading/thread_task_runner_handle.h" +#include "chromecast/base/chromecast_switches.h" +#include "chromecast/base/path_utils.h" +#include "chromecast/browser/metrics/cast_stability_metrics_provider.h" +#include "components/metrics/gpu/gpu_metrics_provider.h" +#include "components/metrics/metrics_service.h" +#include "components/metrics/net/network_metrics_provider.h" +#include "components/metrics/ui/screen_info_metrics_provider.h" +#include "content/public/browser/histogram_fetcher.h" +#include "content/public/browser/network_service_instance.h" +#include "content/public/common/content_switches.h" + +#if defined(OS_LINUX) +#include "chromecast/browser/metrics/external_metrics.h" +#endif // defined(OS_LINUX) + +#if defined(OS_ANDROID) +#include "chromecast/base/android/dumpstate_writer.h" +#endif + +namespace chromecast { +namespace metrics { + +const int kMetricsFetchTimeoutSeconds = 60; + +#if defined(OS_LINUX) +const char kExternalUmaEventsRelativePath[] = "metrics/uma-events"; +const char kPlatformUmaEventsPath[] = "/data/share/chrome/metrics/uma-events"; +#endif // defined(OS_LINUX) + +CastBrowserMetrics::CastBrowserMetrics( + std::unique_ptr<CastMetricsServiceClient> metrics_service_client) { + metrics_service_client_ = std::move(metrics_service_client); + metrics_service_client_->SetCallbacks( + base::BindRepeating(&CastBrowserMetrics::CollectFinalMetricsForLog, + base::Unretained(this)), + base::BindRepeating(&CastBrowserMetrics::ProcessExternalEvents, + base::Unretained(this))); +} + +CastBrowserMetrics::~CastBrowserMetrics() { +#if defined(OS_LINUX) + DCHECK(!external_metrics_); + DCHECK(!platform_metrics_); +#endif // defined(OS_LINUX) +} + +void CastBrowserMetrics::Initialize() { + metrics_service_client_->InitializeMetricsService(); + + auto* metrics_service = metrics_service_client_->GetMetricsService(); + auto stability_provider_unique_ptr = + std::make_unique<CastStabilityMetricsProvider>( + metrics_service, metrics_service_client_->pref_service()); +#if defined(OS_LINUX) + auto* stability_provider = stability_provider_unique_ptr.get(); +#endif // defined(OS_LINUX) + metrics_service->RegisterMetricsProvider( + std::move(stability_provider_unique_ptr)); + + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (!command_line->HasSwitch(switches::kDisableGpu)) { + metrics_service->RegisterMetricsProvider( + std::make_unique<::metrics::GPUMetricsProvider>()); + + // TODO(gfhuang): Does ChromeCast actually need metrics about screen info? + // crbug.com/541577 + metrics_service->RegisterMetricsProvider( + std::make_unique<::metrics::ScreenInfoMetricsProvider>()); + } + + metrics_service->RegisterMetricsProvider( + std::make_unique<::metrics::NetworkMetricsProvider>( + content::CreateNetworkConnectionTrackerAsyncGetter())); + + metrics_service_client_->StartMetricsService(); + +#if defined(OS_LINUX) + // Start external metrics collection, which feeds data from external + // processes into the main external metrics. + external_metrics_ = new ExternalMetrics( + stability_provider, + GetHomePathASCII(kExternalUmaEventsRelativePath).value()); + external_metrics_->Start(); + platform_metrics_ = + new ExternalMetrics(stability_provider, kPlatformUmaEventsPath); + platform_metrics_->Start(); +#endif // defined(OS_LINUX) +} + +void CastBrowserMetrics::Finalize() { +#if !defined(OS_ANDROID) + // Set clean_shutdown bit. + metrics_service_client_->GetMetricsService()->RecordCompletedSessionEnd(); +#endif // !defined(OS_ANDROID) + +#if defined(OS_LINUX) + // Stop metrics service cleanly before destructing CastMetricsServiceClient. + // The pointer will be deleted in StopAndDestroy(). + external_metrics_->StopAndDestroy(); + external_metrics_ = nullptr; + platform_metrics_->StopAndDestroy(); + platform_metrics_ = nullptr; +#endif // defined(OS_LINUX) + + metrics_service_client_->Finalize(); +} + +void CastBrowserMetrics::CollectFinalMetricsForLog( + const base::Closure& done_callback) { + // Asynchronously fetch metrics data from child processes. Since this method + // is called on log upload, metrics that occur between log upload and child + // process termination will not be uploaded. + content::FetchHistogramsAsynchronously( + base::ThreadTaskRunnerHandle::Get(), done_callback, + base::TimeDelta::FromSeconds(kMetricsFetchTimeoutSeconds)); +} + +void CastBrowserMetrics::ProcessExternalEvents(const base::Closure& cb) { +#if defined(OS_LINUX) + external_metrics_->ProcessExternalEvents( + base::Bind(&ExternalMetrics::ProcessExternalEvents, + base::Unretained(platform_metrics_), cb)); +#else + cb.Run(); +#endif // defined(OS_LINUX) +} + +} // namespace metrics +} // namespace chromecast
diff --git a/chromecast/browser/metrics/cast_browser_metrics.h b/chromecast/browser/metrics/cast_browser_metrics.h new file mode 100644 index 0000000..f3c2fb57 --- /dev/null +++ b/chromecast/browser/metrics/cast_browser_metrics.h
@@ -0,0 +1,52 @@ +// Copyright 2019 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 CHROMECAST_BROWSER_METRICS_CAST_BROWSER_METRICS_H_ +#define CHROMECAST_BROWSER_METRICS_CAST_BROWSER_METRICS_H_ + +#include <memory> + +#include "base/callback_forward.h" +#include "base/macros.h" +#include "build/build_config.h" +#include "chromecast/metrics/cast_metrics_service_client.h" + +namespace chromecast { +namespace metrics { + +class ExternalMetrics; + +class CastBrowserMetrics { + public: + explicit CastBrowserMetrics( + std::unique_ptr<CastMetricsServiceClient> metrics_service_client); + ~CastBrowserMetrics(); + void Initialize(); + void Finalize(); + + // Processes all events from shared file. This should be used to consume all + // events in the file before shutdown. This function is safe to call from any + // thread. + void ProcessExternalEvents(const base::Closure& cb); + void CollectFinalMetricsForLog(const base::Closure& done_callback); + + metrics::CastMetricsServiceClient* metrics_service_client() const { + return metrics_service_client_.get(); + } + + private: + std::unique_ptr<CastMetricsServiceClient> metrics_service_client_; + +#if defined(OS_LINUX) + ExternalMetrics* external_metrics_ = nullptr; + ExternalMetrics* platform_metrics_ = nullptr; +#endif // defined(OS_LINUX) + + DISALLOW_COPY_AND_ASSIGN(CastBrowserMetrics); +}; + +} // namespace metrics +} // namespace chromecast + +#endif // CHROMECAST_BROWSER_METRICS_CAST_BROWSER_METRICS_H_
diff --git a/chromecast/browser/metrics/cast_metrics_prefs.cc b/chromecast/browser/metrics/cast_metrics_prefs.cc index 2755cca..03e4d6c0 100644 --- a/chromecast/browser/metrics/cast_metrics_prefs.cc +++ b/chromecast/browser/metrics/cast_metrics_prefs.cc
@@ -4,8 +4,8 @@ #include "chromecast/browser/metrics/cast_metrics_prefs.h" -#include "chromecast/browser/metrics/cast_metrics_service_client.h" #include "chromecast/browser/metrics/cast_stability_metrics_provider.h" +#include "chromecast/metrics/cast_metrics_service_client.h" #include "components/metrics/metrics_service.h" namespace chromecast {
diff --git a/chromecast/browser/metrics/cast_stability_metrics_provider.cc b/chromecast/browser/metrics/cast_stability_metrics_provider.cc index e22c89f..b6666b6 100644 --- a/chromecast/browser/metrics/cast_stability_metrics_provider.cc +++ b/chromecast/browser/metrics/cast_stability_metrics_provider.cc
@@ -10,7 +10,7 @@ #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "chromecast/base/pref_names.h" -#include "chromecast/browser/metrics/cast_metrics_service_client.h" +#include "chromecast/metrics/cast_metrics_service_client.h" #include "components/metrics/metrics_service.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h"
diff --git a/chromecast/metrics/BUILD.gn b/chromecast/metrics/BUILD.gn new file mode 100644 index 0000000..15e7dc4 --- /dev/null +++ b/chromecast/metrics/BUILD.gn
@@ -0,0 +1,27 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//chromecast/chromecast.gni") + +cast_source_set("metrics") { + sources = [ + "cast_metrics_service_client.cc", + "cast_metrics_service_client.h", + ] + + deps = [ + "//base", + "//base:i18n", + "//chromecast/base", + "//chromecast/base:cast_sys_info_util", + "//chromecast/base:cast_version", + "//components/metrics", + "//components/metrics:gpu", + "//components/metrics:net", + "//components/metrics:ui", + "//components/prefs", + "//services/network/public/cpp", + "//third_party/metrics_proto", + ] +}
diff --git a/chromecast/metrics/DEPS b/chromecast/metrics/DEPS new file mode 100644 index 0000000..cb0a439 --- /dev/null +++ b/chromecast/metrics/DEPS
@@ -0,0 +1,6 @@ +include_rules = [ + "+components/metrics", + "+components/prefs", + "+services/network/public", + "+third_party/metrics_proto", +]
diff --git a/chromecast/browser/metrics/cast_metrics_service_client.cc b/chromecast/metrics/cast_metrics_service_client.cc similarity index 69% rename from chromecast/browser/metrics/cast_metrics_service_client.cc rename to chromecast/metrics/cast_metrics_service_client.cc index 645835f..aa6df00 100644 --- a/chromecast/browser/metrics/cast_metrics_service_client.cc +++ b/chromecast/metrics/cast_metrics_service_client.cc
@@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chromecast/browser/metrics/cast_metrics_service_client.h" +#include "chromecast/metrics/cast_metrics_service_client.h" #include "base/bind.h" +#include "base/callback.h" #include "base/command_line.h" #include "base/guid.h" #include "base/i18n/rtl.h" @@ -18,7 +19,6 @@ #include "chromecast/base/path_utils.h" #include "chromecast/base/pref_names.h" #include "chromecast/base/version.h" -#include "chromecast/browser/metrics/cast_stability_metrics_provider.h" #include "chromecast/public/cast_sys_info.h" #include "components/metrics/client_info.h" #include "components/metrics/enabled_state_provider.h" @@ -28,20 +28,12 @@ #include "components/metrics/metrics_service.h" #include "components/metrics/metrics_state_manager.h" #include "components/metrics/net/net_metrics_log_uploader.h" -#include "components/metrics/net/network_metrics_provider.h" #include "components/metrics/ui/screen_info_metrics_provider.h" #include "components/metrics/url_constants.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" -#include "content/public/browser/histogram_fetcher.h" -#include "content/public/browser/network_service_instance.h" -#include "content/public/common/content_switches.h" #include "services/network/public/cpp/shared_url_loader_factory.h" -#if defined(OS_LINUX) -#include "chromecast/browser/metrics/external_metrics.h" -#endif // defined(OS_LINUX) - #if defined(OS_ANDROID) #include "chromecast/base/android/dumpstate_writer.h" #endif @@ -52,7 +44,6 @@ namespace { const int kStandardUploadIntervalMinutes = 5; -const int kMetricsFetchTimeoutSeconds = 60; const char kMetricsOldClientID[] = "user_experience_metrics.client_id"; @@ -60,25 +51,20 @@ const char kClientIdName[] = "Client ID"; #else -#if defined(OS_LINUX) -const char kExternalUmaEventsRelativePath[] = "metrics/uma-events"; -const char kPlatformUmaEventsPath[] = "/data/share/chrome/metrics/uma-events"; -#endif // defined(OS_LINUX) - const struct ChannelMap { const char* chromecast_channel; const ::metrics::SystemProfileProto::Channel chrome_channel; } kMetricsChannelMap[] = { - { "canary-channel", ::metrics::SystemProfileProto::CHANNEL_CANARY }, - { "dev-channel", ::metrics::SystemProfileProto::CHANNEL_DEV }, - { "developer-channel", ::metrics::SystemProfileProto::CHANNEL_DEV }, - { "beta-channel", ::metrics::SystemProfileProto::CHANNEL_BETA }, - { "dogfood-channel", ::metrics::SystemProfileProto::CHANNEL_BETA }, - { "stable-channel", ::metrics::SystemProfileProto::CHANNEL_STABLE }, + {"canary-channel", ::metrics::SystemProfileProto::CHANNEL_CANARY}, + {"dev-channel", ::metrics::SystemProfileProto::CHANNEL_DEV}, + {"developer-channel", ::metrics::SystemProfileProto::CHANNEL_DEV}, + {"beta-channel", ::metrics::SystemProfileProto::CHANNEL_BETA}, + {"dogfood-channel", ::metrics::SystemProfileProto::CHANNEL_BETA}, + {"stable-channel", ::metrics::SystemProfileProto::CHANNEL_STABLE}, }; -::metrics::SystemProfileProto::Channel -GetReleaseChannelFromUpdateChannelName(const std::string& channel_name) { +::metrics::SystemProfileProto::Channel GetReleaseChannelFromUpdateChannelName( + const std::string& channel_name) { if (channel_name.empty()) return ::metrics::SystemProfileProto::CHANNEL_UNKNOWN; @@ -152,7 +138,7 @@ LOG(ERROR) << "Invalid client id from platform: " << force_client_id_ << " from platform."; } - return std::unique_ptr<::metrics::ClientInfo>(); + return nullptr; } int32_t CastMetricsServiceClient::GetProduct() { @@ -206,8 +192,7 @@ CHECK(!CAST_IS_DEBUG_BUILD() || channel != ::metrics::SystemProfileProto::CHANNEL_STABLE); const bool is_official_build = - build_number > 0 && - !CAST_IS_DEBUG_BUILD() && + build_number > 0 && !CAST_IS_DEBUG_BUILD() && channel != ::metrics::SystemProfileProto::CHANNEL_UNKNOWN; if (!is_official_build) version_string.append("-devel"); @@ -217,12 +202,16 @@ void CastMetricsServiceClient::CollectFinalMetricsForLog( const base::Closure& done_callback) { - // Asynchronously fetch metrics data from child processes. Since this method - // is called on log upload, metrics that occur between log upload and child - // process termination will not be uploaded. - content::FetchHistogramsAsynchronously( - task_runner_, done_callback, - base::TimeDelta::FromSeconds(kMetricsFetchTimeoutSeconds)); + if (collect_final_metrics_cb_) + collect_final_metrics_cb_.Run(done_callback); +} + +void CastMetricsServiceClient::SetCallbacks( + base::RepeatingCallback<void(const base::Closure&)> + collect_final_metrics_cb, + base::RepeatingCallback<void(const base::Closure&)> external_events_cb) { + collect_final_metrics_cb_ = collect_final_metrics_cb; + external_events_cb_ = external_events_cb; } GURL CastMetricsServiceClient::GetMetricsServerUrl() { @@ -243,10 +232,9 @@ base::StringPiece mime_type, ::metrics::MetricsLogUploader::MetricServiceType service_type, const ::metrics::MetricsLogUploader::UploadCallback& on_upload_complete) { - return std::unique_ptr<::metrics::MetricsLogUploader>( - new ::metrics::NetMetricsLogUploader(url_loader_factory_, server_url, - insecure_server_url, mime_type, - service_type, on_upload_complete)); + return std::make_unique<::metrics::NetMetricsLogUploader>( + url_loader_factory_, server_url, insecure_server_url, mime_type, + service_type, on_upload_complete); } base::TimeDelta CastMetricsServiceClient::GetStandardUploadInterval() { @@ -280,44 +268,23 @@ : delegate_(delegate), pref_service_(pref_service), client_info_loaded_(false), -#if defined(OS_LINUX) - external_metrics_(nullptr), - platform_metrics_(nullptr), -#endif // defined(OS_LINUX) task_runner_(base::ThreadTaskRunnerHandle::Get()), - url_loader_factory_(url_loader_factory) { -} + url_loader_factory_(url_loader_factory) {} -CastMetricsServiceClient::~CastMetricsServiceClient() { -#if defined(OS_LINUX) - DCHECK(!external_metrics_); - DCHECK(!platform_metrics_); -#endif // defined(OS_LINUX) -} +CastMetricsServiceClient::~CastMetricsServiceClient() = default; void CastMetricsServiceClient::OnApplicationNotIdle() { metrics_service_->OnApplicationNotIdle(); } -void CastMetricsServiceClient::ProcessExternalEvents(const base::Closure& cb) { -#if defined(OS_LINUX) - external_metrics_->ProcessExternalEvents( - base::Bind(&ExternalMetrics::ProcessExternalEvents, - base::Unretained(platform_metrics_), cb)); -#else - cb.Run(); -#endif // defined(OS_LINUX) -} - -void CastMetricsServiceClient::SetForceClientId( - const std::string& client_id) { +void CastMetricsServiceClient::SetForceClientId(const std::string& client_id) { DCHECK(force_client_id_.empty()); DCHECK(!client_info_loaded_) << "Force client ID must be set before client info is loaded."; force_client_id_ = client_id; } -void CastMetricsServiceClient::Initialize() { +void CastMetricsServiceClient::InitializeMetricsService() { DCHECK(!metrics_state_manager_); metrics_state_manager_ = ::metrics::MetricsStateManager::Create( pref_service_, this, base::string16(), @@ -338,27 +305,9 @@ metrics_state_manager_->ForceClientIdCreation(); // Populate |client_id| to other component parts. SetMetricsClientId(metrics_state_manager_->client_id()); +} - CastStabilityMetricsProvider* stability_provider = - new CastStabilityMetricsProvider(metrics_service_.get(), pref_service_); - metrics_service_->RegisterMetricsProvider( - std::unique_ptr<::metrics::MetricsProvider>(stability_provider)); - - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (!command_line->HasSwitch(switches::kDisableGpu)) { - metrics_service_->RegisterMetricsProvider( - std::unique_ptr<::metrics::MetricsProvider>( - new ::metrics::GPUMetricsProvider)); - - // TODO(gfhuang): Does ChromeCast actually need metrics about screen info? - // crbug.com/541577 - metrics_service_->RegisterMetricsProvider( - std::unique_ptr<::metrics::MetricsProvider>( - new ::metrics::ScreenInfoMetricsProvider)); - } - metrics_service_->RegisterMetricsProvider( - std::make_unique<::metrics::NetworkMetricsProvider>( - content::CreateNetworkConnectionTrackerAsyncGetter())); +void CastMetricsServiceClient::StartMetricsService() { if (delegate_) delegate_->RegisterMetricsProviders(metrics_service_.get()); @@ -370,36 +319,16 @@ if (IsReportingEnabled()) metrics_service_->Start(); - -#if defined(OS_LINUX) - // Start external metrics collection, which feeds data from external - // processes into the main external metrics. - external_metrics_ = new ExternalMetrics( - stability_provider, - GetHomePathASCII(kExternalUmaEventsRelativePath).value()); - external_metrics_->Start(); - platform_metrics_ = - new ExternalMetrics(stability_provider, kPlatformUmaEventsPath); - platform_metrics_->Start(); -#endif // defined(OS_LINUX) } void CastMetricsServiceClient::Finalize() { -#if !defined(OS_ANDROID) - // Set clean_shutdown bit. - metrics_service_->RecordCompletedSessionEnd(); -#endif // !defined(OS_ANDROID) - -#if defined(OS_LINUX) - // Stop metrics service cleanly before destructing CastMetricsServiceClient. - // The pointer will be deleted in StopAndDestroy(). - external_metrics_->StopAndDestroy(); - external_metrics_ = nullptr; - platform_metrics_->StopAndDestroy(); - platform_metrics_ = nullptr; -#endif // defined(OS_LINUX) metrics_service_->Stop(); } +void CastMetricsServiceClient::ProcessExternalEvents(const base::Closure& cb) { + if (external_events_cb_) + external_events_cb_.Run(cb); +} + } // namespace metrics } // namespace chromecast
diff --git a/chromecast/browser/metrics/cast_metrics_service_client.h b/chromecast/metrics/cast_metrics_service_client.h similarity index 85% rename from chromecast/browser/metrics/cast_metrics_service_client.h rename to chromecast/metrics/cast_metrics_service_client.h index 0f056d3a..2162346 100644 --- a/chromecast/browser/metrics/cast_metrics_service_client.h +++ b/chromecast/metrics/cast_metrics_service_client.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROMECAST_BROWSER_METRICS_CAST_METRICS_SERVICE_CLIENT_H_ -#define CHROMECAST_BROWSER_METRICS_CAST_METRICS_SERVICE_CLIENT_H_ +#ifndef CHROMECAST_METRICS_CAST_METRICS_SERVICE_CLIENT_H_ +#define CHROMECAST_METRICS_CAST_METRICS_SERVICE_CLIENT_H_ #include <stdint.h> @@ -48,8 +48,6 @@ virtual ~CastMetricsServiceDelegate() = default; }; -class ExternalMetrics; - class CastMetricsServiceClient : public ::metrics::MetricsServiceClient, public ::metrics::EnabledStateProvider { public: @@ -71,7 +69,8 @@ // thread. void ProcessExternalEvents(const base::Closure& cb); - void Initialize(); + void InitializeMetricsService(); + void StartMetricsService(); void Finalize(); // ::metrics::MetricsServiceClient: @@ -101,6 +100,12 @@ std::string client_id() const { return client_id_; } + PrefService* pref_service() const { return pref_service_; } + void SetCallbacks( + base::RepeatingCallback<void(const base::Closure&)> + collect_final_metrics_cb, + base::RepeatingCallback<void(const base::Closure&)> external_events_cb); + private: std::unique_ptr<::metrics::ClientInfo> LoadClientInfo(); void StoreClientInfo(const ::metrics::ClientInfo& client_info); @@ -111,15 +116,13 @@ std::string force_client_id_; bool client_info_loaded_; -#if defined(OS_LINUX) - ExternalMetrics* external_metrics_; - ExternalMetrics* platform_metrics_; -#endif // defined(OS_LINUX) const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; std::unique_ptr<::metrics::MetricsStateManager> metrics_state_manager_; std::unique_ptr<::metrics::MetricsService> metrics_service_; std::unique_ptr<::metrics::EnabledStateProvider> enabled_state_provider_; scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; + base::RepeatingCallback<void(const base::Closure&)> collect_final_metrics_cb_; + base::RepeatingCallback<void(const base::Closure&)> external_events_cb_; DISALLOW_COPY_AND_ASSIGN(CastMetricsServiceClient); }; @@ -127,4 +130,4 @@ } // namespace metrics } // namespace chromecast -#endif // CHROMECAST_BROWSER_METRICS_CAST_METRICS_SERVICE_CLIENT_H_ +#endif // CHROMECAST_METRICS_CAST_METRICS_SERVICE_CLIENT_H_
diff --git a/components/gwp_asan/client/guarded_page_allocator.cc b/components/gwp_asan/client/guarded_page_allocator.cc index 9bd94c7..9e7ae79 100644 --- a/components/gwp_asan/client/guarded_page_allocator.cc +++ b/components/gwp_asan/client/guarded_page_allocator.cc
@@ -6,6 +6,7 @@ #include <algorithm> #include <memory> +#include <utility> #include "base/bits.h" #include "base/debug/stack_trace.h" @@ -41,16 +42,49 @@ #endif } +template <typename T> +T RandomEviction(std::vector<T>* list) { + DCHECK(!list->empty()); + size_t rand = base::RandGenerator(list->size()); + T out = (*list)[rand]; + (*list)[rand] = list->back(); + list->pop_back(); + return out; +} + } // namespace // TODO: Delete out-of-line constexpr defininitons once C++17 is in use. +constexpr size_t GuardedPageAllocator::kOutOfMemoryCount; constexpr size_t GuardedPageAllocator::kGpaAllocAlignment; +template <typename T> +void GuardedPageAllocator::SimpleFreeList<T>::Initialize(T max_entries) { + max_entries_ = max_entries; + free_list_.reserve(max_entries); +} + +template <typename T> +T GuardedPageAllocator::SimpleFreeList<T>::Allocate() { + if (num_used_entries_ < max_entries_) + return num_used_entries_++; + + DCHECK_LE(free_list_.size(), max_entries_); + return RandomEviction(&free_list_); +} + +template <typename T> +void GuardedPageAllocator::SimpleFreeList<T>::Free(T entry) { + DCHECK_LT(free_list_.size(), max_entries_); + free_list_.push_back(entry); +} + GuardedPageAllocator::GuardedPageAllocator() {} void GuardedPageAllocator::Init(size_t max_alloced_pages, size_t num_metadata, - size_t total_pages) { + size_t total_pages, + OutOfMemoryCallback oom_callback) { CHECK_GT(max_alloced_pages, 0U); CHECK_LE(max_alloced_pages, num_metadata); CHECK_LE(num_metadata, AllocatorState::kMaxMetadata); @@ -59,6 +93,7 @@ max_alloced_pages_ = max_alloced_pages; state_.num_metadata = num_metadata; state_.total_pages = total_pages; + oom_callback_ = std::move(oom_callback); state_.page_size = base::GetPageSize(); @@ -74,8 +109,8 @@ // Obtain this lock exclusively to satisfy the thread-safety annotations, // there should be no risk of a race here. base::AutoLock lock(lock_); - free_metadata_.reserve(num_metadata); - free_slots_.reserve(total_pages); + free_metadata_.Initialize(num_metadata); + free_slots_.Initialize(total_pages); } slot_to_metadata_idx_.resize(total_pages); @@ -199,21 +234,20 @@ AllocatorState::SlotIdx* slot, AllocatorState::MetadataIdx* metadata_idx) { base::AutoLock lock(lock_); - if (num_alloced_pages_ == max_alloced_pages_) + if (num_alloced_pages_ == max_alloced_pages_) { + if (++consecutive_failed_allocations_ == kOutOfMemoryCount) { + if (!oom_hit_) { + oom_hit_ = true; + base::AutoUnlock unlock(lock_); + std::move(oom_callback_).Run(total_allocations_ - kOutOfMemoryCount); + } + } return false; - num_alloced_pages_++; + } - if (num_used_metadata_ < state_.num_metadata) { - *metadata_idx = num_used_metadata_++; - } else { - DCHECK(!free_metadata_.empty()); - DCHECK_LE(free_metadata_.size(), state_.num_metadata); - size_t rand = base::RandGenerator(free_metadata_.size()); - *metadata_idx = free_metadata_[rand]; - free_metadata_[rand] = free_metadata_.back(); - free_metadata_.pop_back(); - DCHECK_EQ(free_metadata_.size(), state_.num_metadata - num_alloced_pages_); - + *slot = free_slots_.Allocate(); + *metadata_idx = free_metadata_.Allocate(); + if (metadata_[*metadata_idx].alloc_ptr) { // Overwrite the outdated slot_to_metadata_idx mapping from the previous use // of this metadata if it's still valid. DCHECK(state_.PointerIsMine(metadata_[*metadata_idx].alloc_ptr)); @@ -222,18 +256,9 @@ slot_to_metadata_idx_[old_slot] = AllocatorState::kInvalidMetadataIdx; } - if (num_used_slots_ < state_.total_pages) { - *slot = num_used_slots_++; - } else { - DCHECK(!free_slots_.empty()); - DCHECK_LE(free_slots_.size(), state_.total_pages); - size_t rand = base::RandGenerator(free_slots_.size()); - *slot = free_slots_[rand]; - free_slots_[rand] = free_slots_.back(); - free_slots_.pop_back(); - DCHECK_EQ(free_slots_.size(), state_.total_pages - num_alloced_pages_); - } - + num_alloced_pages_++; + total_allocations_++; + consecutive_failed_allocations_ = 0; return true; } @@ -244,17 +269,11 @@ DCHECK_LT(metadata_idx, state_.num_metadata); base::AutoLock lock(lock_); - DCHECK_LT(free_slots_.size(), state_.total_pages); - free_slots_.push_back(slot); - - DCHECK_LT(free_metadata_.size(), state_.num_metadata); - free_metadata_.push_back(metadata_idx); + free_slots_.Free(slot); + free_metadata_.Free(metadata_idx); DCHECK_GT(num_alloced_pages_, 0U); num_alloced_pages_--; - - DCHECK_EQ(free_metadata_.size(), num_used_metadata_ - num_alloced_pages_); - DCHECK_EQ(free_slots_.size(), num_used_slots_ - num_alloced_pages_); } void GuardedPageAllocator::RecordAllocationMetadata(
diff --git a/components/gwp_asan/client/guarded_page_allocator.h b/components/gwp_asan/client/guarded_page_allocator.h index 3a032907..502b1b7 100644 --- a/components/gwp_asan/client/guarded_page_allocator.h +++ b/components/gwp_asan/client/guarded_page_allocator.h
@@ -10,6 +10,7 @@ #include <string> #include <vector> +#include "base/callback.h" #include "base/compiler_specific.h" #include "base/gtest_prod_util.h" #include "base/no_destructor.h" @@ -29,9 +30,16 @@ // initialization-time so there is no risk of malloc reentrancy. class GWP_ASAN_EXPORT GuardedPageAllocator { public: + // Number of consecutive allocations that fail due to lack of available pages + // before we call the OOM callback. + static constexpr size_t kOutOfMemoryCount = 100; // Default maximum alignment for all returned allocations. static constexpr size_t kGpaAllocAlignment = 16; + // Callback used to report the allocator running out of memory, reports the + // number of successful allocations before running out of memory. + using OutOfMemoryCallback = base::OnceCallback<void(size_t)>; + // Does not allocate any memory for the allocator, to finish initializing call // Init(). GuardedPageAllocator(); @@ -41,7 +49,13 @@ // total_pages pages, where: // 1 <= max_alloced_pages <= num_metadata <= kMaxMetadata // num_metadata <= total_pages <= kMaxSlots - void Init(size_t max_alloced_pages, size_t num_metadata, size_t total_pages); + // + // The OOM callback is called the first time the allocator fails to allocate + // kOutOfMemoryCount allocations consecutively due to lack of memory. + void Init(size_t max_alloced_pages, + size_t num_metadata, + size_t total_pages, + OutOfMemoryCallback oom_callback); // On success, returns a pointer to size bytes of page-guarded memory. On // failure, returns nullptr. The allocation is not guaranteed to be @@ -73,6 +87,27 @@ } private: + // Manages a free list of slot or metadata indices in the range + // [0, max_entries). Access to SimpleFreeList objects must be synchronized. + // + // SimpleFreeList is specifically designed to pre-allocate data in Initialize + // so that it never recurses into malloc/free during Allocate/Free. + template <typename T> + class SimpleFreeList { + public: + void Initialize(T max_entries); + T Allocate(); + void Free(T entry); + + private: + std::vector<T> free_list_; + + // Number of used entries. This counter ensures all free entries are used + // before starting to use random eviction. + T num_used_entries_ = 0; + T max_entries_ = 0; + }; + // Unmaps memory allocated by this class, if Init was called. ~GuardedPageAllocator(); @@ -116,15 +151,8 @@ // Lock that synchronizes allocating/freeing slots between threads. base::Lock lock_; - // Array used to store all free slot indices. - std::vector<AllocatorState::SlotIdx> free_slots_ GUARDED_BY(lock_); - // Array used to store all free metadata indices. - std::vector<AllocatorState::MetadataIdx> free_metadata_ GUARDED_BY(lock_); - - // Number of used slots/metadata. These counters are to make sure we use all - // free metadata/slots before starting to use random eviction. - size_t num_used_slots_ GUARDED_BY(lock_) = 0; - size_t num_used_metadata_ GUARDED_BY(lock_) = 0; + SimpleFreeList<AllocatorState::SlotIdx> free_slots_ GUARDED_BY(lock_); + SimpleFreeList<AllocatorState::MetadataIdx> free_metadata_ GUARDED_BY(lock_); // Number of currently-allocated pages. size_t num_alloced_pages_ GUARDED_BY(lock_) = 0; @@ -139,6 +167,13 @@ // mapping exists.) std::vector<AllocatorState::MetadataIdx> slot_to_metadata_idx_; + // Maintain a count of total allocations and consecutive failed allocations + // to report allocator OOM. + size_t total_allocations_ GUARDED_BY(lock_) = 0; + size_t consecutive_failed_allocations_ GUARDED_BY(lock_) = 0; + bool oom_hit_ GUARDED_BY(lock_) = false; + OutOfMemoryCallback oom_callback_; + // Required for a singleton to access the constructor. friend base::NoDestructor<GuardedPageAllocator>;
diff --git a/components/gwp_asan/client/guarded_page_allocator_unittest.cc b/components/gwp_asan/client/guarded_page_allocator_unittest.cc index b7a6268f..399b62c 100644 --- a/components/gwp_asan/client/guarded_page_allocator_unittest.cc +++ b/components/gwp_asan/client/guarded_page_allocator_unittest.cc
@@ -11,6 +11,7 @@ #include "base/bits.h" #include "base/process/process_metrics.h" +#include "base/test/bind_test_util.h" #include "base/test/gtest_util.h" #include "base/threading/simple_thread.h" #include "build/build_config.h" @@ -25,7 +26,9 @@ class GuardedPageAllocatorTest : public testing::Test { protected: explicit GuardedPageAllocatorTest(size_t max_allocated_pages = kMaxMetadata) { - gpa_.Init(max_allocated_pages, kMaxMetadata, kMaxSlots); + gpa_.Init(max_allocated_pages, kMaxMetadata, kMaxSlots, + base::BindLambdaForTesting( + [&](size_t allocations) { allocator_oom_ = true; })); } // Get a left- or right- aligned allocation (or nullptr on error.) @@ -60,6 +63,7 @@ } GuardedPageAllocator gpa_; + bool allocator_oom_ = false; }; TEST_F(GuardedPageAllocatorTest, SingleAllocDealloc) { @@ -140,6 +144,17 @@ EXPECT_EQ(GetAlignedAllocation(false, 5, page_size * 2), nullptr); } +TEST_F(GuardedPageAllocatorTest, OutOfMemoryCallback) { + for (size_t i = 0; i < kMaxMetadata; i++) + EXPECT_NE(gpa_.Allocate(1), nullptr); + + for (size_t i = 0; i < GuardedPageAllocator::kOutOfMemoryCount - 1; i++) + EXPECT_EQ(gpa_.Allocate(1), nullptr); + EXPECT_FALSE(allocator_oom_); + EXPECT_EQ(gpa_.Allocate(1), nullptr); + EXPECT_TRUE(allocator_oom_); +} + class GuardedPageAllocatorParamTest : public GuardedPageAllocatorTest, public testing::WithParamInterface<size_t> {
diff --git a/components/gwp_asan/client/sampling_malloc_shims.cc b/components/gwp_asan/client/sampling_malloc_shims.cc index 4e23af21..c5f381e 100644 --- a/components/gwp_asan/client/sampling_malloc_shims.cc +++ b/components/gwp_asan/client/sampling_malloc_shims.cc
@@ -7,6 +7,7 @@ #include <algorithm> #include "base/allocator/allocator_shim.h" +#include "base/bind_helpers.h" #include "base/compiler_specific.h" #include "base/logging.h" #include "base/no_destructor.h" @@ -254,7 +255,7 @@ size_t sampling_frequency) { static crash_reporter::CrashKeyString<24> malloc_crash_key(kMallocCrashKey); gpa = new GuardedPageAllocator(); - gpa->Init(max_allocated_pages, num_metadata, total_pages); + gpa->Init(max_allocated_pages, num_metadata, total_pages, base::DoNothing()); malloc_crash_key.Set(gpa->GetCrashKey()); sampling_state.Init(sampling_frequency); base::allocator::InsertAllocatorDispatch(&g_allocator_dispatch);
diff --git a/components/gwp_asan/client/sampling_partitionalloc_shims.cc b/components/gwp_asan/client/sampling_partitionalloc_shims.cc index 200cdb3..544f3a2 100644 --- a/components/gwp_asan/client/sampling_partitionalloc_shims.cc +++ b/components/gwp_asan/client/sampling_partitionalloc_shims.cc
@@ -7,6 +7,7 @@ #include <algorithm> #include "base/allocator/partition_allocator/partition_alloc.h" +#include "base/bind_helpers.h" #include "base/logging.h" #include "base/partition_alloc_buildflags.h" #include "components/crash/core/common/crash_key.h" @@ -85,7 +86,7 @@ static crash_reporter::CrashKeyString<24> pa_crash_key( kPartitionAllocCrashKey); gpa = new GuardedPageAllocator(); - gpa->Init(max_allocated_pages, num_metadata, total_pages); + gpa->Init(max_allocated_pages, num_metadata, total_pages, base::DoNothing()); pa_crash_key.Set(gpa->GetCrashKey()); sampling_state.Init(sampling_frequency); total_allocations = total_pages;
diff --git a/components/gwp_asan/crash_handler/crash_analyzer_unittest.cc b/components/gwp_asan/crash_handler/crash_analyzer_unittest.cc index 54061ae..01d526d 100644 --- a/components/gwp_asan/crash_handler/crash_analyzer_unittest.cc +++ b/components/gwp_asan/crash_handler/crash_analyzer_unittest.cc
@@ -9,6 +9,7 @@ #include <utility> #include <vector> +#include "base/bind_helpers.h" #include "base/debug/stack_trace.h" #include "base/test/gtest_util.h" #include "base/test/metrics/histogram_tester.h" @@ -43,7 +44,7 @@ class CrashAnalyzerTest : public testing::Test { protected: void SetUp() final { - gpa_.Init(1, 1, 1); + gpa_.Init(1, 1, 1, base::DoNothing()); InitializeSnapshot(); }
diff --git a/components/gwp_asan/crash_handler/crash_handler_unittest.cc b/components/gwp_asan/crash_handler/crash_handler_unittest.cc index 80e86a2..e2d685a8 100644 --- a/components/gwp_asan/crash_handler/crash_handler_unittest.cc +++ b/components/gwp_asan/crash_handler/crash_handler_unittest.cc
@@ -9,6 +9,7 @@ #include <string> #include <vector> +#include "base/bind_helpers.h" #include "base/command_line.h" #include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" @@ -77,7 +78,7 @@ MULTIPROCESS_TEST_MAIN(CrashingProcess) { base::NoDestructor<GuardedPageAllocator> gpa; gpa->Init(AllocatorState::kMaxMetadata, AllocatorState::kMaxMetadata, - kTotalPages); + kTotalPages, base::DoNothing()); base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); base::FilePath directory = cmd_line->GetSwitchValuePath("directory");
diff --git a/components/network_session_configurator/browser/network_session_configurator_unittest.cc b/components/network_session_configurator/browser/network_session_configurator_unittest.cc index fae07a36..2ba9af7 100644 --- a/components/network_session_configurator/browser/network_session_configurator_unittest.cc +++ b/components/network_session_configurator/browser/network_session_configurator_unittest.cc
@@ -127,8 +127,7 @@ EXPECT_EQ(0, params_.quic_initial_rtt_for_handshake_milliseconds); EXPECT_FALSE(params_.quic_allow_server_migration); EXPECT_TRUE(params_.quic_host_whitelist.empty()); - EXPECT_EQ(net::kDefaultRetransmittableOnWireTimeoutMillisecs, - params_.quic_retransmittable_on_wire_timeout_milliseconds); + EXPECT_EQ(0, params_.quic_retransmittable_on_wire_timeout_milliseconds); net::HttpNetworkSession::Params default_params; EXPECT_EQ(default_params.quic_supported_versions,
diff --git a/components/resources/OWNERS b/components/resources/OWNERS index 456bcda..704da9fb 100644 --- a/components/resources/OWNERS +++ b/components/resources/OWNERS
@@ -18,6 +18,7 @@ per-file neterror*=mmenke@chromium.org per-file neterror*=file://net/OWNERS per-file ntp_tiles_resources.grdp=file://components/ntp_tiles/OWNERS +per-file onboarding_welcome_scaled_resources.grdp=file://ui/webui/PLATFORM_OWNERS per-file offline_pages_resources.grdp=file://components/offline_pages/OWNERS per-file proximity_auth*=tengs@chromium.org per-file printing_resources.grdp=file://printing/OWNERS
diff --git a/components/resources/components_scaled_resources.grd b/components/resources/components_scaled_resources.grd index 2403267..379fb2f9 100644 --- a/components/resources/components_scaled_resources.grd +++ b/components/resources/components_scaled_resources.grd
@@ -16,6 +16,7 @@ <part file="crash_scaled_resources.grdp" /> <part file="flags_ui_scaled_resources.grdp" /> <part file="neterror_scaled_resources.grdp" /> + <part file="onboarding_welcome_scaled_resources.grdp" /> <part file="version_ui_scaled_resources.grdp" /> <!-- Generic resources -->
diff --git a/components/resources/onboarding_welcome_scaled_resources.grdp b/components/resources/onboarding_welcome_scaled_resources.grdp new file mode 100644 index 0000000..d083b940 --- /dev/null +++ b/components/resources/onboarding_welcome_scaled_resources.grdp
@@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<grit-part> + <if expr="not is_android and not is_ios and _google_chrome"> + <structure type="chrome_scaled_image" name="IDS_ONBOARDING_WELCOME_SEARCH" file="google_chrome/welcome/search.png" /> + </if> +</grit-part>
diff --git a/components/services/pdf_compositor/DEPS b/components/services/pdf_compositor/DEPS index 0c41bb8f..1f84ab9 100644 --- a/components/services/pdf_compositor/DEPS +++ b/components/services/pdf_compositor/DEPS
@@ -9,7 +9,6 @@ "+printing/common", "+services/service_manager/public/cpp", "+services/service_manager/public/mojom", - "+services/ws/public/mojom/constants.mojom.h", # UI service name. "+skia", "+third_party/skia", "+third_party/blink/public/platform", # Test web sandbox support.
diff --git a/components/services/pdf_compositor/pdf_compositor_service.cc b/components/services/pdf_compositor/pdf_compositor_service.cc index 517ed845..cc751c39 100644 --- a/components/services/pdf_compositor/pdf_compositor_service.cc +++ b/components/services/pdf_compositor/pdf_compositor_service.cc
@@ -18,7 +18,6 @@ #include "content/public/utility/utility_thread.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "services/service_manager/public/cpp/connector.h" -#include "services/ws/public/mojom/constants.mojom.h" #if defined(OS_WIN) #include "content/public/child/dwrite_font_proxy_init_win.h"
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn index 270277f..789d2a1 100644 --- a/components/viz/common/BUILD.gn +++ b/components/viz/common/BUILD.gn
@@ -47,6 +47,8 @@ defines = [ "VIZ_METAL_CONTEXT_PROVIDER_IMPLEMENTATION" ] sources = [ + "gpu/metal_api_proxy.h", + "gpu/metal_api_proxy.mm", "gpu/metal_context_provider.h", "gpu/metal_context_provider.mm", "viz_metal_context_provider_export.h", @@ -59,6 +61,7 @@ deps = [ "//base", "//ui/gfx", + "//ui/gl", ] libs = [
diff --git a/components/viz/common/gpu/DEPS b/components/viz/common/gpu/DEPS index dcd56b3..cd1304f 100644 --- a/components/viz/common/gpu/DEPS +++ b/components/viz/common/gpu/DEPS
@@ -10,3 +10,9 @@ "+third_party/skia/include/gpu", "+third_party/vulkan/include", ] + +specific_include_rules = { + "metal_api_proxy.mm": [ + "+ui/gl", + ] +}
diff --git a/components/viz/common/gpu/metal_api_proxy.h b/components/viz/common/gpu/metal_api_proxy.h new file mode 100644 index 0000000..8db4dac --- /dev/null +++ b/components/viz/common/gpu/metal_api_proxy.h
@@ -0,0 +1,33 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_VIZ_COMMON_GPU_METAL_API_PROXY_H_ +#define COMPONENTS_VIZ_COMMON_GPU_METAL_API_PROXY_H_ + +#import <Metal/Metal.h> + +#include "base/mac/availability.h" +#include "base/mac/scoped_nsobject.h" + +namespace gl { +class ProgressReporter; +} // namespace gl + +// The MTLDeviceProxy wraps all calls to an MTLDevice. It reports progress +// to the GPU watchdog to prevent the watchdog from killing the GPU process +// when progress is being made. +API_AVAILABLE(macos(10.11)) +@interface MTLDeviceProxy : NSObject <MTLDevice> { + base::scoped_nsprotocol<id<MTLDevice>> device_; + + // Weak pointer to the progress reporter used to avoid watchdog timeouts. + // This must be re-set to nullptr when it is no longer known to be valid. + gl::ProgressReporter* progressReporter_; +} + +- (id)initWithDevice:(id<MTLDevice>)device; +- (void)setProgressReporter:(gl::ProgressReporter*)progressReporter; +@end + +#endif // COMPONENTS_VIZ_COMMON_GPU_METAL_API_PROXY_H_
diff --git a/components/viz/common/gpu/metal_api_proxy.mm b/components/viz/common/gpu/metal_api_proxy.mm new file mode 100644 index 0000000..5cd5333a --- /dev/null +++ b/components/viz/common/gpu/metal_api_proxy.mm
@@ -0,0 +1,256 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/viz/common/gpu/metal_api_proxy.h" + +#include "ui/gl/progress_reporter.h" + +@implementation MTLDeviceProxy +- (id)initWithDevice:(id<MTLDevice>)device { + if (self = [super init]) + device_.reset(device, base::scoped_policy::RETAIN); + return self; +} + +- (void)setProgressReporter:(gl::ProgressReporter*)progressReporter { + progressReporter_ = progressReporter; +} + +// Wrappers that add a gl::ScopedProgressReporter around calls to the true +// MTLDevice. For a given method, the method name is fn, return type is R, the +// argument types are A0,A1,A2,A3, and the argument names are a0,a1,a2,a3. +#define PROXY_METHOD0(R, fn) \ + -(R)fn { \ + return [device_ fn]; \ + } +#define PROXY_METHOD1(R, fn, A0) \ + -(R)fn : (A0)a0 { \ + return [device_ fn:a0]; \ + } +#define PROXY_METHOD2(R, fn, A0, a1, A1) \ + -(R)fn : (A0)a0 a1 : (A1)a1 { \ + return [device_ fn:a0 a1:a1]; \ + } +#define PROXY_METHOD0_SLOW(R, fn) \ + -(R)fn { \ + gl::ScopedProgressReporter scoped_reporter(progressReporter_); \ + return [device_ fn]; \ + } +#define PROXY_METHOD1_SLOW(R, fn, A0) \ + -(R)fn : (A0)a0 { \ + gl::ScopedProgressReporter scoped_reporter(progressReporter_); \ + return [device_ fn:a0]; \ + } +#define PROXY_METHOD2_SLOW(R, fn, A0, a1, A1) \ + -(R)fn : (A0)a0 a1 : (A1)a1 { \ + gl::ScopedProgressReporter scoped_reporter(progressReporter_); \ + return [device_ fn:a0 a1:a1]; \ + } +#define PROXY_METHOD3_SLOW(R, fn, A0, a1, A1, a2, A2) \ + -(R)fn : (A0)a0 a1 : (A1)a1 a2 : (A2)a2 { \ + gl::ScopedProgressReporter scoped_reporter(progressReporter_); \ + return [device_ fn:a0 a1:a1 a2:a2]; \ + } +#define PROXY_METHOD4_SLOW(R, fn, A0, a1, A1, a2, A2, a3, A3) \ + -(R)fn : (A0)a0 a1 : (A1)a1 a2 : (A2)a2 a3 : (A3)a3 { \ + gl::ScopedProgressReporter scoped_reporter(progressReporter_); \ + return [device_ fn:a0 a1:a1 a2:a2 a3:a3]; \ + } + +// Disable availability warnings for the calls to |device_| in the macros. (The +// relevant availability guards are already present in the MTLDevice protocol +// for |self|). +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + +// Wrapped implementation of the MTLDevice protocol in which some methods +// have a gl::ScopedProgressReporter. The methods implemented using macros +// with the _SLOW suffix are the ones that create a gl::ScopedProgressReporter. +// The rule of thumb is that methods that could potentially do a GPU allocation +// or a shader compilation are marked as SLOW. +PROXY_METHOD0(NSString*, name) +PROXY_METHOD0(uint64_t, registryID) +PROXY_METHOD0(MTLSize, maxThreadsPerThreadgroup) +PROXY_METHOD0(BOOL, isLowPower) +PROXY_METHOD0(BOOL, isHeadless) +PROXY_METHOD0(BOOL, isRemovable) +PROXY_METHOD0(uint64_t, recommendedMaxWorkingSetSize) +PROXY_METHOD0(BOOL, isDepth24Stencil8PixelFormatSupported) +PROXY_METHOD0(MTLReadWriteTextureTier, readWriteTextureSupport) +PROXY_METHOD0(MTLArgumentBuffersTier, argumentBuffersSupport) +PROXY_METHOD0(BOOL, areRasterOrderGroupsSupported) +PROXY_METHOD0(NSUInteger, currentAllocatedSize) +PROXY_METHOD0(NSUInteger, maxThreadgroupMemoryLength) +PROXY_METHOD0(BOOL, areProgrammableSamplePositionsSupported) +PROXY_METHOD0_SLOW(nullable id<MTLCommandQueue>, newCommandQueue) +PROXY_METHOD1_SLOW(nullable id<MTLCommandQueue>, + newCommandQueueWithMaxCommandBufferCount, + NSUInteger) +PROXY_METHOD1(MTLSizeAndAlign, + heapTextureSizeAndAlignWithDescriptor, + MTLTextureDescriptor*) +PROXY_METHOD2(MTLSizeAndAlign, + heapBufferSizeAndAlignWithLength, + NSUInteger, + options, + MTLResourceOptions) +PROXY_METHOD1_SLOW(nullable id<MTLHeap>, + newHeapWithDescriptor, + MTLHeapDescriptor*) +PROXY_METHOD2_SLOW(nullable id<MTLBuffer>, + newBufferWithLength, + NSUInteger, + options, + MTLResourceOptions) +PROXY_METHOD3_SLOW(nullable id<MTLBuffer>, + newBufferWithBytes, + const void*, + length, + NSUInteger, + options, + MTLResourceOptions) +PROXY_METHOD4_SLOW(nullable id<MTLBuffer>, + newBufferWithBytesNoCopy, + void*, + length, + NSUInteger, + options, + MTLResourceOptions, + deallocator, + void (^__nullable)(void* pointer, NSUInteger length)) +PROXY_METHOD1(nullable id<MTLDepthStencilState>, + newDepthStencilStateWithDescriptor, + MTLDepthStencilDescriptor*) +PROXY_METHOD1_SLOW(nullable id<MTLTexture>, + newTextureWithDescriptor, + MTLTextureDescriptor*) +PROXY_METHOD3_SLOW(nullable id<MTLTexture>, + newTextureWithDescriptor, + MTLTextureDescriptor*, + iosurface, + IOSurfaceRef, + plane, + NSUInteger) +PROXY_METHOD1_SLOW(nullable id<MTLSamplerState>, + newSamplerStateWithDescriptor, + MTLSamplerDescriptor*) +PROXY_METHOD0_SLOW(nullable id<MTLLibrary>, newDefaultLibrary) +PROXY_METHOD2_SLOW(nullable id<MTLLibrary>, + newDefaultLibraryWithBundle, + NSBundle*, + error, + __autoreleasing NSError**) +PROXY_METHOD2_SLOW(nullable id<MTLLibrary>, + newLibraryWithFile, + NSString*, + error, + __autoreleasing NSError**) +PROXY_METHOD2_SLOW(nullable id<MTLLibrary>, + newLibraryWithURL, + NSURL*, + error, + __autoreleasing NSError**) +PROXY_METHOD2_SLOW(nullable id<MTLLibrary>, + newLibraryWithData, + dispatch_data_t, + error, + __autoreleasing NSError**) +PROXY_METHOD3_SLOW(nullable id<MTLLibrary>, + newLibraryWithSource, + NSString*, + options, + nullable MTLCompileOptions*, + error, + __autoreleasing NSError**) +PROXY_METHOD3_SLOW(void, + newLibraryWithSource, + NSString*, + options, + nullable MTLCompileOptions*, + completionHandler, + MTLNewLibraryCompletionHandler) +PROXY_METHOD2_SLOW(nullable id<MTLRenderPipelineState>, + newRenderPipelineStateWithDescriptor, + MTLRenderPipelineDescriptor*, + error, + __autoreleasing NSError**) +PROXY_METHOD4_SLOW(nullable id<MTLRenderPipelineState>, + newRenderPipelineStateWithDescriptor, + MTLRenderPipelineDescriptor*, + options, + MTLPipelineOption, + reflection, + MTLAutoreleasedRenderPipelineReflection* __nullable, + error, + __autoreleasing NSError**) +PROXY_METHOD2_SLOW(void, + newRenderPipelineStateWithDescriptor, + MTLRenderPipelineDescriptor*, + completionHandler, + MTLNewRenderPipelineStateCompletionHandler) +PROXY_METHOD3_SLOW(void, + newRenderPipelineStateWithDescriptor, + MTLRenderPipelineDescriptor*, + options, + MTLPipelineOption, + completionHandler, + MTLNewRenderPipelineStateWithReflectionCompletionHandler) +PROXY_METHOD2_SLOW(nullable id<MTLComputePipelineState>, + newComputePipelineStateWithFunction, + id<MTLFunction>, + error, + __autoreleasing NSError**) +PROXY_METHOD4_SLOW(nullable id<MTLComputePipelineState>, + newComputePipelineStateWithFunction, + id<MTLFunction>, + options, + MTLPipelineOption, + reflection, + MTLAutoreleasedComputePipelineReflection* __nullable, + error, + __autoreleasing NSError**) +PROXY_METHOD2_SLOW(void, + newComputePipelineStateWithFunction, + id<MTLFunction>, + completionHandler, + MTLNewComputePipelineStateCompletionHandler) +PROXY_METHOD3_SLOW(void, + newComputePipelineStateWithFunction, + id<MTLFunction>, + options, + MTLPipelineOption, + completionHandler, + MTLNewComputePipelineStateWithReflectionCompletionHandler) +PROXY_METHOD4_SLOW(nullable id<MTLComputePipelineState>, + newComputePipelineStateWithDescriptor, + MTLComputePipelineDescriptor*, + options, + MTLPipelineOption, + reflection, + MTLAutoreleasedComputePipelineReflection* __nullable, + error, + __autoreleasing NSError**) +PROXY_METHOD3_SLOW(void, + newComputePipelineStateWithDescriptor, + MTLComputePipelineDescriptor*, + options, + MTLPipelineOption, + completionHandler, + MTLNewComputePipelineStateWithReflectionCompletionHandler) +PROXY_METHOD0_SLOW(nullable id<MTLFence>, newFence) +PROXY_METHOD1(BOOL, supportsFeatureSet, MTLFeatureSet) +PROXY_METHOD1(BOOL, supportsTextureSampleCount, NSUInteger) +PROXY_METHOD1(NSUInteger, + minimumLinearTextureAlignmentForPixelFormat, + MTLPixelFormat) +PROXY_METHOD2(void, + getDefaultSamplePositions, + MTLSamplePosition*, + count, + NSUInteger) +PROXY_METHOD1_SLOW(nullable id<MTLArgumentEncoder>, + newArgumentEncoderWithArguments, + NSArray<MTLArgumentDescriptor*>*) +#pragma clang diagnostic pop +@end
diff --git a/components/viz/common/gpu/metal_context_provider.h b/components/viz/common/gpu/metal_context_provider.h index 71ad85f..f69c33ac 100644 --- a/components/viz/common/gpu/metal_context_provider.h +++ b/components/viz/common/gpu/metal_context_provider.h
@@ -18,6 +18,10 @@ using MTLDevicePtr = MTLDeviceProtocol*; #endif +namespace gl { +class ProgressReporter; +} // namespace gl + namespace viz { // The MetalContextProvider provides a Metal-backed GrContext. @@ -30,6 +34,11 @@ virtual GrContext* GetGrContext() = 0; virtual MTLDevicePtr GetMTLDevice() = 0; + + // Set the progress reported used to prevent watchdog timeouts during longer + // sequences of Metal API calls. It is guaranteed that no further calls to + // |progress_reporter| will be made after |this| is destroyed. + virtual void SetProgressReporter(gl::ProgressReporter* progress_reporter) = 0; }; } // namespace viz
diff --git a/components/viz/common/gpu/metal_context_provider.mm b/components/viz/common/gpu/metal_context_provider.mm index 07af97e..6d7d0263 100644 --- a/components/viz/common/gpu/metal_context_provider.mm +++ b/components/viz/common/gpu/metal_context_provider.mm
@@ -5,6 +5,7 @@ #include "components/viz/common/gpu/metal_context_provider.h" #include "base/mac/scoped_nsobject.h" +#include "components/viz/common/gpu/metal_api_proxy.h" #include "third_party/skia/include/gpu/GrContext.h" #import <Metal/Metal.h> @@ -16,9 +17,8 @@ struct API_AVAILABLE(macos(10.11)) MetalContextProviderImpl : public MetalContextProvider { public: - explicit MetalContextProviderImpl( - base::scoped_nsprotocol<id<MTLDevice>> device) - : device_(device) { + explicit MetalContextProviderImpl(id<MTLDevice> device) { + device_.reset([[MTLDeviceProxy alloc] initWithDevice:device]); command_queue_.reset([device_ newCommandQueue]); // GrContext::MakeMetal will take ownership of the objects passed in. Retain // the objects before passing them to MakeMetal so that the objects in @@ -27,12 +27,19 @@ GrContext::MakeMetal([device_ retain], [command_queue_ retain]); DCHECK(gr_context_); } - ~MetalContextProviderImpl() override {} + ~MetalContextProviderImpl() override { + // Because there are no guarantees that |device_| will not outlive |this|, + // un-set the progress reporter on |device_|. + [device_ setProgressReporter:nullptr]; + } + void SetProgressReporter(gl::ProgressReporter* progress_reporter) override { + [device_ setProgressReporter:progress_reporter]; + } GrContext* GetGrContext() override { return gr_context_.get(); } MTLDevicePtr GetMTLDevice() override { return device_.get(); } private: - base::scoped_nsprotocol<id<MTLDevice>> device_; + base::scoped_nsobject<MTLDeviceProxy> device_; base::scoped_nsprotocol<id<MTLCommandQueue>> command_queue_; sk_sp<GrContext> gr_context_; @@ -57,7 +64,7 @@ if (!device_to_use) device_to_use.reset(MTLCreateSystemDefaultDevice()); if (device_to_use) - return std::make_unique<MetalContextProviderImpl>(device_to_use); + return std::make_unique<MetalContextProviderImpl>(device_to_use.get()); DLOG(ERROR) << "Failed to create MTLDevice."; } // If no device was found, or if the macOS version is too old for Metal,
diff --git a/content/browser/devtools/devtools_background_services_context_impl.cc b/content/browser/devtools/devtools_background_services_context_impl.cc index 1c1331c..21ba92eb 100644 --- a/content/browser/devtools/devtools_background_services_context_impl.cc +++ b/content/browser/devtools/devtools_background_services_context_impl.cc
@@ -60,7 +60,8 @@ BrowserContext* browser_context, scoped_refptr<ServiceWorkerContextWrapper> service_worker_context) : browser_context_(browser_context), - service_worker_context_(std::move(service_worker_context)) { + service_worker_context_(std::move(service_worker_context)), + weak_ptr_factory_(this) { DCHECK_CURRENTLY_ON(BrowserThread::UI); auto expiration_times = @@ -147,7 +148,7 @@ FROM_HERE, {BrowserThread::IO}, base::BindOnce(&DevToolsBackgroundServicesContextImpl:: GetLoggedBackgroundServiceEventsOnIO, - weak_ptr_factory_io_.GetWeakPtr(), service, + weak_ptr_factory_.GetWeakPtr(), service, std::move(callback))); } @@ -160,7 +161,7 @@ service_worker_context_->GetUserDataForAllRegistrationsByKeyPrefix( CreateEntryKeyPrefix(service), base::BindOnce(&DevToolsBackgroundServicesContextImpl::DidGetUserData, - weak_ptr_factory_io_.GetWeakPtr(), std::move(callback))); + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } void DevToolsBackgroundServicesContextImpl::DidGetUserData( @@ -208,7 +209,7 @@ FROM_HERE, {BrowserThread::IO}, base::BindOnce(&DevToolsBackgroundServicesContextImpl:: ClearLoggedBackgroundServiceEventsOnIO, - weak_ptr_factory_io_.GetWeakPtr(), service)); + weak_ptr_factory_.GetWeakPtr(), service)); } void DevToolsBackgroundServicesContextImpl:: @@ -233,7 +234,7 @@ FROM_HERE, {BrowserThread::IO}, base::BindOnce( &DevToolsBackgroundServicesContextImpl::LogBackgroundServiceEventOnIO, - weak_ptr_factory_io_.GetWeakPtr(), service_worker_registration_id, + weak_ptr_factory_.GetWeakPtr(), service_worker_registration_id, origin, service, event_name, instance_id, event_metadata)); } @@ -256,7 +257,7 @@ FROM_HERE, {BrowserThread::UI}, base::BindOnce( &DevToolsBackgroundServicesContextImpl::OnRecordingTimeExpired, - weak_ptr_factory_ui_.GetWeakPtr(), ServiceToProtoEnum(service))); + weak_ptr_factory_.GetWeakPtr(), ServiceToProtoEnum(service))); return; } @@ -280,7 +281,7 @@ FROM_HERE, {BrowserThread::UI}, base::BindOnce( &DevToolsBackgroundServicesContextImpl::NotifyEventObservers, - weak_ptr_factory_ui_.GetWeakPtr(), std::move(event))); + weak_ptr_factory_.GetWeakPtr(), std::move(event))); } void DevToolsBackgroundServicesContextImpl::NotifyEventObservers(
diff --git a/content/browser/devtools/devtools_background_services_context_impl.h b/content/browser/devtools/devtools_background_services_context_impl.h index c378fb54..2a5b560 100644 --- a/content/browser/devtools/devtools_background_services_context_impl.h +++ b/content/browser/devtools/devtools_background_services_context_impl.h
@@ -136,10 +136,7 @@ base::ObserverList<EventObserver> observers_; - base::WeakPtrFactory<DevToolsBackgroundServicesContextImpl> - weak_ptr_factory_ui_{this}; - base::WeakPtrFactory<DevToolsBackgroundServicesContextImpl> - weak_ptr_factory_io_{this}; + base::WeakPtrFactory<DevToolsBackgroundServicesContextImpl> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(DevToolsBackgroundServicesContextImpl); };
diff --git a/content/browser/devtools/protocol/background_service_handler.cc b/content/browser/devtools/protocol/background_service_handler.cc index d5a174a..17b91e8 100644 --- a/content/browser/devtools/protocol/background_service_handler.cc +++ b/content/browser/devtools/protocol/background_service_handler.cc
@@ -22,12 +22,6 @@ } else if (service_name == BackgroundService::ServiceNameEnum::BackgroundSync) { return devtools::proto::BackgroundService::BACKGROUND_SYNC; - } else if (service_name == - BackgroundService::ServiceNameEnum::PushMessaging) { - return devtools::proto::BackgroundService::PUSH_MESSAGING; - } else if (service_name == - BackgroundService::ServiceNameEnum::Notifications) { - return devtools::proto::BackgroundService::NOTIFICATIONS; } return devtools::proto::BackgroundService::UNKNOWN; } @@ -38,10 +32,6 @@ return BackgroundService::ServiceNameEnum::BackgroundFetch; case devtools::proto::BackgroundService::BACKGROUND_SYNC: return BackgroundService::ServiceNameEnum::BackgroundSync; - case devtools::proto::BackgroundService::PUSH_MESSAGING: - return BackgroundService::ServiceNameEnum::PushMessaging; - case devtools::proto::BackgroundService::NOTIFICATIONS: - return BackgroundService::ServiceNameEnum::Notifications; default: NOTREACHED(); }
diff --git a/content/browser/devtools/protocol/system_info_handler.cc b/content/browser/devtools/protocol/system_info_handler.cc index 83b9de3c..66730f3 100644 --- a/content/browser/devtools/protocol/system_info_handler.cc +++ b/content/browser/devtools/protocol/system_info_handler.cc
@@ -117,6 +117,8 @@ .SetDeviceId(device.device_id) .SetVendorString(device.vendor_string) .SetDeviceString(device.device_string) + .SetDriverVendor(device.driver_vendor) + .SetDriverVersion(device.driver_version) .Build(); }
diff --git a/content/browser/fileapi/browser_file_system_helper.cc b/content/browser/fileapi/browser_file_system_helper.cc index e278fff..7caf1a9a 100644 --- a/content/browser/fileapi/browser_file_system_helper.cc +++ b/content/browser/fileapi/browser_file_system_helper.cc
@@ -251,22 +251,24 @@ file_system_context->CrackURL(file_system_file.url); std::string register_name; - std::string filesystem_id = isolated_context->RegisterFileSystemForPath( - file_system_url.type(), file_system_url.filesystem_id(), - file_system_url.path(), ®ister_name); + storage::IsolatedContext::ScopedFSHandle filesystem = + isolated_context->RegisterFileSystemForPath( + file_system_url.type(), file_system_url.filesystem_id(), + file_system_url.path(), ®ister_name); - if (!filesystem_id.empty()) { - // Grant the permission iff the ID is valid. - security_policy->GrantReadFileSystem(child_id, filesystem_id); + if (filesystem.is_valid()) { + // Grant the permission iff the ID is valid. This will also keep the FS + // alive after |filesystem| goes out of scope. + security_policy->GrantReadFileSystem(child_id, filesystem.id()); } // Note: We are using the origin URL provided by the sender here. It may be // different from the receiver's. file_system_file.url = GURL( storage::GetIsolatedFileSystemRootURIString( - file_system_url.origin().GetURL(), filesystem_id, std::string()) + file_system_url.origin().GetURL(), filesystem.id(), std::string()) .append(register_name)); - file_system_file.filesystem_id = filesystem_id; + file_system_file.filesystem_id = filesystem.id(); } }
diff --git a/content/browser/media/session/audio_focus_delegate_android.cc b/content/browser/media/session/audio_focus_delegate_android.cc index bb4e9cc..f835e2b 100644 --- a/content/browser/media/session/audio_focus_delegate_android.cc +++ b/content/browser/media/session/audio_focus_delegate_android.cc
@@ -7,6 +7,7 @@ #include "base/android/jni_android.h" #include "content/browser/media/session/media_session_impl.h" #include "jni/AudioFocusDelegate_jni.h" +#include "media/base/media_switches.h" #include "services/media_session/public/mojom/audio_focus.mojom.h" using base::android::JavaParamRef; @@ -61,7 +62,8 @@ void AudioFocusDelegateAndroid::OnSuspend(JNIEnv*, const JavaParamRef<jobject>&) { - if (!media_session_->IsActive()) + if (!media_session_->IsActive() || + !base::FeatureList::IsEnabled(media::kAudioFocusLossSuspendMediaSession)) return; media_session_->Suspend(MediaSession::SuspendType::kSystem);
diff --git a/content/browser/media/session/audio_focus_delegate_android.h b/content/browser/media/session/audio_focus_delegate_android.h index f4a3b13..e8f4436 100644 --- a/content/browser/media/session/audio_focus_delegate_android.h +++ b/content/browser/media/session/audio_focus_delegate_android.h
@@ -62,7 +62,6 @@ // Weak pointer because |this| is owned by |media_session_|. MediaSessionImpl* media_session_; base::android::ScopedJavaGlobalRef<jobject> j_media_session_delegate_; - DISALLOW_COPY_AND_ASSIGN(AudioFocusDelegateAndroid); };
diff --git a/content/browser/native_file_system/file_system_chooser.cc b/content/browser/native_file_system/file_system_chooser.cc index f2413e5..31ad1c93 100644 --- a/content/browser/native_file_system/file_system_chooser.cc +++ b/content/browser/native_file_system/file_system_chooser.cc
@@ -157,13 +157,19 @@ result.reserve(files.size()); for (const auto& path : files) { std::string base_name; - std::string file_system_id = isolated_context->RegisterFileSystemForPath( - storage::kFileSystemTypeNativeLocal, std::string(), path, &base_name); + storage::IsolatedContext::ScopedFSHandle file_system = + isolated_context->RegisterFileSystemForPath( + storage::kFileSystemTypeNativeLocal, std::string(), path, + &base_name); + + // TODO(https://crbug.com/955185): Properly refcount file system in handle + // implementations, rather than just leaking them like this. + storage::IsolatedContext::GetInstance()->AddReference(file_system.id()); base::FilePath root_path = - isolated_context->CreateVirtualRootPath(file_system_id); + isolated_context->CreateVirtualRootPath(file_system.id()); base::FilePath isolated_path = root_path.AppendASCII(base_name); - result.push_back({file_system_id, isolated_path}); + result.push_back({file_system.id(), isolated_path}); } if (type_ == blink::mojom::ChooseFileSystemEntryType::kSaveFile) {
diff --git a/content/browser/service_worker/service_worker_installed_scripts_sender.cc b/content/browser/service_worker/service_worker_installed_scripts_sender.cc index 7e35d7a..f5cab8fad 100644 --- a/content/browser/service_worker/service_worker_installed_scripts_sender.cc +++ b/content/browser/service_worker/service_worker_installed_scripts_sender.cc
@@ -168,12 +168,20 @@ kResponseReaderError: owner_->SetStartWorkerStatusCode( blink::ServiceWorkerStatusCode::kErrorDiskCache); - // Abort the worker by deleting from the registration since the data was - // corrupted. + + // Break the Mojo connection with the renderer so the service worker knows + // to stop waiting for the script data to arrive and terminate. Note that + // DeleteVersion() below sends the Stop IPC, but without breaking the + // connection here, the service worker would be blocked waiting for the + // script data and won't respond to Stop. + manager_.reset(); + binding_.Close(); + + // Delete the registration data since the data was corrupted. if (owner_->context()) { ServiceWorkerRegistration* registration = owner_->context()->GetLiveRegistration(owner_->registration_id()); - // This ends up with destructing |this|. + // This can destruct |this|. registration->DeleteVersion(owner_); } return; @@ -182,9 +190,9 @@ case ServiceWorkerInstalledScriptReader::FinishedReason::kConnectionError: case ServiceWorkerInstalledScriptReader::FinishedReason:: kMetaDataSenderError: - // Notify the renderer that a connection failure happened. Usually the - // failure means the renderer gets killed, and the error handler of - // EmbeddedWorkerInstance is invoked soon. + // Break the Mojo connection with the renderer. This usually causes the + // service worker to stop, and the error handler of EmbeddedWorkerInstance + // is invoked soon. manager_.reset(); binding_.Close(); return;
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc index 4942a43f..ce7224a 100644 --- a/content/browser/webauth/authenticator_impl_unittest.cc +++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -3744,6 +3744,33 @@ EXPECT_TRUE(HasUV(callback_receiver)); } +TEST_F(ResidentKeyAuthenticatorImplTest, WithAppIDExtension) { + // Setting an AppID value for a resident-key request should be ignored. + device::VirtualCtap2Device::Config config; + config.u2f_support = true; + config.pin_support = true; + config.resident_key_support = true; + config.cred_protect_support = true; + virtual_device_.SetCtap2Config(config); + ASSERT_TRUE(virtual_device_.mutable_state()->InjectResidentKey( + /*credential_id=*/{{4, 3, 2, 1}}, kTestRelyingPartyId, + /*user_id=*/{{1, 2, 3, 4}}, "test@example.com", "Test User")); + + TestServiceManagerContext smc; + AuthenticatorPtr authenticator = ConnectToAuthenticator(); + TestGetAssertionCallback callback_receiver; + // |SelectAccount| should not be called when there's only a single response. + test_client_.expected_accounts = "<invalid>"; + + PublicKeyCredentialRequestOptionsPtr options = get_credential_options(); + options->appid = kTestOrigin1; + + authenticator->GetAssertion(std::move(options), callback_receiver.callback()); + callback_receiver.WaitForCallback(); + EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status()); + EXPECT_TRUE(HasUV(callback_receiver)); +} + #if defined(OS_WIN) // Requests with a credProtect extension that have |enforce_protection_policy| // set should be rejected if the Windows WebAuthn API doesn't support
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt index 217b1c9..48498ec 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -49,12 +49,6 @@ crbug.com/874620 [ linux nvidia ] conformance2/glsl3/const-struct-from-array-as-function-parameter.html [ Failure ] crbug.com/874620 [ opengl win nvidia ] conformance2/glsl3/const-struct-from-array-as-function-parameter.html [ Failure ] -# TODO(shrekshao): Remove the following two Fail expectations -# (draw-buffers and fs-color-type-mismatch-color-buffer-type) -# after applying the new draw buffers validation -crbug.com/927908 conformance2/rendering/draw-buffers.html [ Failure ] -crbug.com/927908 conformance2/rendering/fs-color-type-mismatch-color-buffer-type.html [ Failure ] - # Unsuppress after both # https://chromium-review.googlesource.com/1558678 and # https://github.com/KhronosGroup/WebGL/pull/2878 land and are rolled
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt index 257bf61c..e2b9ad3 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -60,11 +60,6 @@ # ======================== # Fails on all platforms -# TODO(shrekshao): Remove this after applying the new draw buffer -# validation. And then uncomment the failure expectation for -# angle bug 1523 (L160) -crbug.com/927908 conformance/extensions/webgl-draw-buffers.html [ Failure ] - # Need to implement new error semantics # https://github.com/KhronosGroup/WebGL/pull/2607 crbug.com/849572 conformance/extensions/angle-instanced-arrays-out-of-bounds.html [ Failure ] @@ -91,7 +86,7 @@ crbug.com/735483 conformance/rendering/texture-switch-performance.html [ Skip ] crbug.com/951628 [ passthrough ] conformance/rendering/blending.html [ Failure ] -# TODO(shrekhao): Restore failure expectation for +# TODO(shrekshao): Restore failure expectation for # ['win', 'nvidia', 'passthrough', 'd3d11'], bug=737016 # as Flaky after 953120 is fixed. # And restore ['linux', 'intel'], bug=928530 as Fail @@ -105,7 +100,7 @@ crbug.com/665521 [ intel opengl passthrough ] conformance/glsl/constructors/glsl-construct-mat2.html [ Failure ] # Passthrough command decoder / OpenGL / AMD -# crbug.com/1523 [ amd opengl linux pass through ] conformance/extensions/webgl-draw-buffers.html [ Failure ] +crbug.com/1523 [ amd opengl linux passthrough ] conformance/extensions/webgl-draw-buffers.html [ Failure ] crbug.com/665521 [ amd opengl passthrough ] conformance/glsl/constructors/glsl-construct-mat2.html [ Failure ] crbug.com/665521 [ amd opengl passthrough ] conformance/glsl/constructors/glsl-construct-vec-mat-corner-cases.html [ Failure ] @@ -276,6 +271,7 @@ crbug.com/angleproject/2914 [ win vulkan passthrough ] conformance/textures/misc/texture-copying-feedback-loops.html [ Failure ] crbug.com/angleproject/2913 [ win vulkan passthrough ] conformance/textures/misc/texture-hd-dpi.html [ Failure ] crbug.com/angleproject/2722 [ win vulkan passthrough ] conformance/textures/misc/texture-mips.html [ Failure ] +crbug.com/angleproject/3469 [ win vulkan passthrough ] conformance/extensions/webgl-draw-buffers.html [ Failure ] # Note: the following test crashes so it's skipped. http://anglebug.com/3352 crbug.com/angleproject/2921 [ win vulkan passthrough ] conformance/uniforms/out-of-bounds-uniform-array-access.html [ Skip ]
diff --git a/device/fido/get_assertion_task.cc b/device/fido/get_assertion_task.cc index e0824c5..97d7690 100644 --- a/device/fido/get_assertion_task.cc +++ b/device/fido/get_assertion_task.cc
@@ -23,7 +23,8 @@ bool ctap2_device_supports_u2f = device.device_info() && base::ContainsKey(device.device_info()->versions, ProtocolVersion::kU2f); - return request.alternative_application_parameter && ctap2_device_supports_u2f; + return request.alternative_application_parameter && + ctap2_device_supports_u2f && !request.allow_list.empty(); } } // namespace
diff --git a/docs/gwp_asan.md b/docs/gwp_asan.md index 55d2153a..90cdc7a 100644 --- a/docs/gwp_asan.md +++ b/docs/gwp_asan.md
@@ -27,8 +27,6 @@ allocation. That way though we may not be able to report the metadata for an old allocation, we will not report incorrect stack traces. -Allocations are sampled to the GuardedPageAllocator using an [allocator shim.](/base/allocator/README.md) - ## Crash handler The allocator is designed so that memory errors with GWP-ASan allocations @@ -49,10 +47,10 @@ ## Status -GWP-ASan is currently only implemented for the system allocator (e.g. not -PartitionAlloc/Oilpan/v8) on Windows and macOS. It is currently enabled by -default. The allocator parameters can be manually modified by using the -following invocation: +GWP-ASan is implemented for malloc and PartitionAlloc, but not for Oilpan or v8, +on Windows and macOS. It is currently enabled by default for malloc. The +allocator parameters can be manually modified by using an invocation like the +following: ```shell chrome --enable-features="GwpAsanMalloc<Study" \ @@ -60,14 +58,30 @@ --force-fieldtrial-params=Study.Group1:MaxAllocations/128/MaxMetadata/255/TotalPages/4096/AllocationSamplingFrequency/1000/ProcessSamplingProbability/1.0 ``` -GWP-ASan is tuned more aggressively in canary/dev (to increase the likelihood we -catch newly introduced bugs) and for the browser process (because of its -importance and sheer number of allocations.) +GWP-ASan is tuned more aggressively in canary/dev, to increase the likelihood we +catch newly introduced bugs, and for specific processes depending on the +particular allocator. A [hotlist of bugs discovered by by GWP-ASan](https://bugs.chromium.org/p/chromium/issues/list?can=1&q=Hotlist%3DGWP-ASan) exists, though GWP-ASan crashes are filed without external visibility by default. +## Limitations + +- GWP-ASan is configured with a small fixed-size amount of memory, so + long-lived allocations can quickly deplete the page pool and lead the + allocator to run out of memory. Depending on the sampling frequency and + distribution of allocation lifetimes this may lead to only allocations early + in the process lifetime being sampled. +- Allocations over a page in size are not sampled. +- The allocator skips zero-size allocations. Zero-size allocations on some + platforms return valid pointers and may be subject to lifetime and bounds + issues. +- GWP-ASan does not intercept allocations for Oilpan or the v8 GC. +- GWP-ASan does not hook PDFium's fork of PartitionAlloc. +- Right-aligned allocations to catch overflows are not perfectly right-aligned, + so small out-of-bounds accesses may be missed. + ## Testing There is [not yet](https://crbug.com/910751) a way to intentionally trigger a
diff --git a/extensions/browser/api/file_handlers/app_file_handler_util.cc b/extensions/browser/api/file_handlers/app_file_handler_util.cc index ca3bc53..96fd9b3 100644 --- a/extensions/browser/api/file_handlers/app_file_handler_util.cc +++ b/extensions/browser/api/file_handlers/app_file_handler_util.cc
@@ -285,9 +285,11 @@ storage::IsolatedContext::GetInstance(); DCHECK(isolated_context); - result.filesystem_id = isolated_context->RegisterFileSystemForPath( - storage::kFileSystemTypeNativeForPlatformApp, std::string(), path, - &result.registered_name); + storage::IsolatedContext::ScopedFSHandle filesystem = + isolated_context->RegisterFileSystemForPath( + storage::kFileSystemTypeNativeForPlatformApp, std::string(), path, + &result.registered_name); + result.filesystem_id = filesystem.id(); content::ChildProcessSecurityPolicy* policy = content::ChildProcessSecurityPolicy::GetInstance();
diff --git a/extensions/browser/api/runtime/runtime_api.cc b/extensions/browser/api/runtime/runtime_api.cc index 24732a0..c88b8dd5 100644 --- a/extensions/browser/api/runtime/runtime_api.cc +++ b/extensions/browser/api/runtime/runtime_api.cc
@@ -736,14 +736,16 @@ std::string relative_path = kPackageDirectoryPath; base::FilePath path = extension_->path(); - std::string filesystem_id = isolated_context->RegisterFileSystemForPath( - storage::kFileSystemTypeNativeLocal, std::string(), path, &relative_path); + storage::IsolatedContext::ScopedFSHandle filesystem = + isolated_context->RegisterFileSystemForPath( + storage::kFileSystemTypeNativeLocal, std::string(), path, + &relative_path); content::ChildProcessSecurityPolicy* policy = content::ChildProcessSecurityPolicy::GetInstance(); - policy->GrantReadFileSystem(source_process_id(), filesystem_id); + policy->GrantReadFileSystem(source_process_id(), filesystem.id()); std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); - dict->SetString("fileSystemId", filesystem_id); + dict->SetString("fileSystemId", filesystem.id()); dict->SetString("baseName", relative_path); return RespondNow(OneArgument(std::move(dict))); }
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index ee96fba..0596bb4 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h
@@ -1399,6 +1399,7 @@ AUTOTESTPRIVATE_SETSHELFALIGNMENT = 1336, BLUETOOTH_RECORDPAIRING = 1337, FILEMANAGERPRIVATE_SETARCSTORAGETOASTSHOWNFLAG = 1338, + INPUTMETHODPRIVATE_SETCOMPOSITIONRANGE = 1339, // Last entry: Add new entries above, then run: // python tools/metrics/histograms/update_extension_histograms.py ENUM_BOUNDARY
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index d95fb380..211bfd81 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -6447,6 +6447,7 @@ const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(mailbox_data); DCHECK(mailbox.Verify()) << "CreateAndTexStorage2DSharedImageCHROMIUM was " "passed an invalid mailbox."; + DCHECK(mailbox.IsSharedImage()); GLuint client_id; GetIdHandler(SharedIdNamespaces::kTextures)->MakeIds(this, 0, 1, &client_id); helper_->CreateAndTexStorage2DSharedImageINTERNALImmediate(client_id, GL_NONE, @@ -6471,6 +6472,7 @@ DCHECK(mailbox.Verify()) << "CreateAndTexStorage2DSharedImageWithInternalFormatCHROMIUM was " "passed an invalid mailbox."; + DCHECK(mailbox.IsSharedImage()); GLuint client_id; GetIdHandler(SharedIdNamespaces::kTextures)->MakeIds(this, 0, 1, &client_id); helper_->CreateAndTexStorage2DSharedImageINTERNALImmediate(
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc index 77861ecf..173c599 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -3586,7 +3586,7 @@ GLbyte data[GL_MAILBOX_SIZE_CHROMIUM]; }; - Mailbox mailbox = Mailbox::Generate(); + Mailbox mailbox = Mailbox::GenerateForSharedImage(); Cmds expected; expected.cmd.Init(kTexturesStartId, GL_NONE, mailbox.name); GLuint id = gl_->CreateAndTexStorage2DSharedImageCHROMIUM(mailbox.name); @@ -3601,7 +3601,7 @@ GLbyte data[GL_MAILBOX_SIZE_CHROMIUM]; }; - Mailbox mailbox = Mailbox::Generate(); + Mailbox mailbox = Mailbox::GenerateForSharedImage(); const GLenum kFormat = GL_RGBA; Cmds expected; expected.cmd.Init(kTexturesStartId, kFormat, mailbox.name);
diff --git a/gpu/command_buffer/service/shared_context_state.cc b/gpu/command_buffer/service/shared_context_state.cc index 2721214..a6befd9 100644 --- a/gpu/command_buffer/service/shared_context_state.cc +++ b/gpu/command_buffer/service/shared_context_state.cc
@@ -90,6 +90,11 @@ gl::ProgressReporter* progress_reporter) { progress_reporter_ = progress_reporter; +#if defined(OS_MACOSX) + if (metal_context_provider_) + metal_context_provider_->SetProgressReporter(progress_reporter); +#endif + if (GrContextIsGL()) { DCHECK(context_->IsCurrent(nullptr)); sk_sp<GrGLInterface> interface(gl::init::CreateGrGLInterface(
diff --git a/headless/app/headless_shell.cc b/headless/app/headless_shell.cc index a993a1d8..57eb874c 100644 --- a/headless/app/headless_shell.cc +++ b/headless/app/headless_shell.cc
@@ -372,7 +372,11 @@ void HeadlessShell::OnReadyState( std::unique_ptr<runtime::EvaluateResult> result) { - if (result->GetResult()->GetValue()->is_string()) { + // result->GetResult() can be nullptr if + // HeadlessDevToolsClientImpl::DispatchMessageReply sees an error. + // It shouldn't, because the result is actually non-optional according to + // js_protocol.pdl; but there is no good way to graft that into here. Sigh. + if (result->GetResult() && result->GetResult()->GetValue()->is_string()) { std::stringstream stream(result->GetResult()->GetValue()->GetString()); std::string ready_state; std::string url;
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 2e364d0c..16fa56b 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -500,6 +500,13 @@ #endif }; +// Only affects Android. Suspends a media session when audio focus is lost; when +// this setting is disabled, an Android media session will not be suspended when +// Audio focus is lost. This is used by Cast which sometimes needs to drive +// multiple media sessions. +const base::Feature kAudioFocusLossSuspendMediaSession{ + "AudioFocusMediaSession", base::FEATURE_ENABLED_BY_DEFAULT}; + // Enables the internal Media Session logic without enabling the Media Session // service. const base::Feature kInternalMediaSession {
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index 3bd59ea6..0f530b26 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -94,6 +94,7 @@ // alongside the definition of their values in the .cc file. MEDIA_EXPORT extern const base::Feature kAudioFocusDuckFlash; +MEDIA_EXPORT extern const base::Feature kAudioFocusLossSuspendMediaSession; MEDIA_EXPORT extern const base::Feature kAutoplayIgnoreWebAudio; MEDIA_EXPORT extern const base::Feature kAutoplayDisableSettings; MEDIA_EXPORT extern const base::Feature kAutoplayWhitelistSettings;
diff --git a/media/filters/pipeline_controller.cc b/media/filters/pipeline_controller.cc index bd05ebdc..5d42944 100644 --- a/media/filters/pipeline_controller.cc +++ b/media/filters/pipeline_controller.cc
@@ -177,6 +177,11 @@ if (state_ == State::PLAYING_OR_SUSPENDED) { waiting_for_seek_ = false; state_ = pipeline_->IsSuspended() ? State::SUSPENDED : State::PLAYING; + + // It's possible for a Suspend() call to come in during startup. If we've + // completed a suspended startup, we should clear that now. + if (state_ == State::SUSPENDED) + pending_suspend_ = false; } if (state_ == State::PLAYING) { @@ -188,12 +193,15 @@ // properly fixed. if (old_state == State::RESUMING) { DCHECK(!pipeline_->IsSuspended()); + DCHECK(!pending_resume_); + resumed_cb_.Run(); } } if (state_ == State::SUSPENDED) { DCHECK(pipeline_->IsSuspended()); + DCHECK(!pending_suspend_); // Warning: possibly reentrant. The state may change inside this callback. // It must be safe to call Dispatch() twice in a row here. @@ -219,7 +227,11 @@ return; } - if (pending_resume_ && state_ == State::SUSPENDED) { + // In additional to the standard |pending_resume_| case, if we completed a + // suspended startup, but a Seek() came in, we need to resume the pipeline to + // complete the seek before calling |seeked_cb_|. + if ((pending_resume_ || (pending_startup_ && pending_seek_)) && + state_ == State::SUSPENDED) { // If there is a pending seek, resume to that time instead... if (pending_seek_) { seek_time_ = pending_seek_time_;
diff --git a/media/filters/pipeline_controller_unittest.cc b/media/filters/pipeline_controller_unittest.cc index 56f09a80..56ba5839 100644 --- a/media/filters/pipeline_controller_unittest.cc +++ b/media/filters/pipeline_controller_unittest.cc
@@ -184,6 +184,47 @@ EXPECT_TRUE(pipeline_controller_.IsStable()); } +TEST_F(PipelineControllerTest, StartSuspendedSeekAndResume) { + EXPECT_FALSE(pipeline_controller_.IsStable()); + PipelineStatusCB start_cb; + EXPECT_CALL(*pipeline_, Start(_, _, _, _, _)).WillOnce(SaveArg<4>(&start_cb)); + pipeline_controller_.Start(Pipeline::StartType::kSuspendAfterMetadata, + &demuxer_, this, false, true); + Mock::VerifyAndClear(pipeline_); + + // Initiate a seek before the pipeline completes suspended startup. + base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5); + EXPECT_CALL(demuxer_, StartWaitingForSeek(seek_time)); + pipeline_controller_.Seek(seek_time, true); + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(was_seeked_); + + PipelineStatusCB resume_cb; + EXPECT_CALL(*pipeline_, Resume(_, _, _)) + .WillOnce(DoAll(SaveArg<2>(&resume_cb))); + EXPECT_CALL(*pipeline_, GetMediaTime()) + .WillRepeatedly(Return(base::TimeDelta())); + + EXPECT_CALL(*pipeline_, IsSuspended()).WillRepeatedly(Return(true)); + EXPECT_FALSE(pipeline_controller_.IsStable()); + Complete(start_cb); + + EXPECT_FALSE(pipeline_controller_.IsStable()); + EXPECT_FALSE(pipeline_controller_.IsPipelineSuspended()); + EXPECT_FALSE(pipeline_controller_.IsSuspended()); + Mock::VerifyAndClear(pipeline_); + + EXPECT_CALL(*pipeline_, IsSuspended()).WillRepeatedly(Return(false)); + Complete(resume_cb); + EXPECT_TRUE(was_seeked_); + was_seeked_ = false; + + EXPECT_TRUE(pipeline_controller_.IsStable()); + EXPECT_FALSE(pipeline_controller_.IsPipelineSuspended()); + EXPECT_FALSE(pipeline_controller_.IsSuspended()); + Mock::VerifyAndClear(pipeline_); +} + TEST_F(PipelineControllerTest, StartSuspendedAndResume) { EXPECT_FALSE(pipeline_controller_.IsStable()); PipelineStatusCB start_cb;
diff --git a/mojo/public/tools/bindings/chromium_bindings_configuration.gni b/mojo/public/tools/bindings/chromium_bindings_configuration.gni index ecbb510..d70eb62d 100644 --- a/mojo/public/tools/bindings/chromium_bindings_configuration.gni +++ b/mojo/public/tools/bindings/chromium_bindings_configuration.gni
@@ -41,7 +41,6 @@ "//services/resource_coordinator/public/cpp/typemaps.gni", "//services/service_manager/public/cpp/typemaps.gni", "//services/tracing/public/mojom/typemaps.gni", - "//services/ws/public/mojom/ime/typemaps.gni", "//services/viz/privileged/cpp/typemaps.gni", "//services/viz/privileged/interfaces/compositing/typemaps.gni", "//services/viz/public/cpp/compositing/typemaps.gni",
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index 3bff221..d3ed27d 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc
@@ -108,8 +108,7 @@ quic_goaway_sessions_on_ip_change(false), quic_idle_connection_timeout_seconds(kIdleConnectionTimeoutSeconds), quic_reduced_ping_timeout_seconds(quic::kPingTimeoutSecs), - quic_retransmittable_on_wire_timeout_milliseconds( - kDefaultRetransmittableOnWireTimeoutMillisecs), + quic_retransmittable_on_wire_timeout_milliseconds(0), quic_max_time_before_crypto_handshake_seconds( quic::kMaxTimeForCryptoHandshakeSecs), quic_max_idle_time_before_crypto_handshake_seconds(
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index 9de62fae..d6caef9c 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h
@@ -179,7 +179,8 @@ // a connection was timed out with open streams. int quic_reduced_ping_timeout_seconds; // Maximum time that a session can have no retransmittable packets on the - // wire. + // wire. Set to zero if not specified and no retransmittable PING will be + // sent to peer when the wire has no retransmittable packets. int quic_retransmittable_on_wire_timeout_milliseconds; // Maximum time the session can be alive before crypto handshake is // finished.
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc index 251b304..579e769e 100644 --- a/net/quic/quic_chromium_client_session.cc +++ b/net/quic/quic_chromium_client_session.cc
@@ -819,7 +819,7 @@ } connect_timing_.dns_start = dns_resolution_start_time; connect_timing_.dns_end = dns_resolution_end_time; - if (migrate_session_early_v2_) { + if (!retransmittable_on_wire_timeout.IsZero()) { connection->set_retransmittable_on_wire_timeout( retransmittable_on_wire_timeout); }
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc index 78f9bf3..fa3dbbf6 100644 --- a/net/quic/quic_network_transaction_unittest.cc +++ b/net/quic/quic_network_transaction_unittest.cc
@@ -1277,6 +1277,8 @@ CreateSession(); SendRequestAndExpectQuicResponse("hello!"); + EXPECT_TRUE(mock_quic_data.AllReadDataConsumed()); + EXPECT_TRUE(mock_quic_data.AllWriteDataConsumed()); } TEST_P(QuicNetworkTransactionTest, TooLargeResponseHeaders) {
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc index 40bd5be..7a73796 100644 --- a/net/quic/quic_stream_factory.cc +++ b/net/quic/quic_stream_factory.cc
@@ -1137,6 +1137,12 @@ if (migrate_sessions_early_v2 || retry_on_alternate_network_before_handshake) DCHECK(migrate_sessions_on_network_change_v2); + if (retransmittable_on_wire_timeout_milliseconds == 0 && + migrate_sessions_early_v2) { + retransmittable_on_wire_timeout_ = quic::QuicTime::Delta::FromMilliseconds( + kDefaultRetransmittableOnWireTimeoutMillisecs); + } + // goaway_sessions_on_ip_change and close_sessions_on_ip_change should never // be simultaneously set to true. DCHECK(!(close_sessions_on_ip_change_ && goaway_sessions_on_ip_change_));
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h index b7a988f6..bae47ec 100644 --- a/net/quic/quic_stream_factory.h +++ b/net/quic/quic_stream_factory.h
@@ -83,8 +83,8 @@ // Sessions can migrate if they have been idle for less than this period. const int kDefaultIdleSessionMigrationPeriodSeconds = 30; -// The maximum time allowed to have no retransmittable packets on the wire -// (after sending the first retransmittable packet) if +// The default maximum time allowed to have no retransmittable packets on the +// wire (after sending the first retransmittable packet) if // |migrate_session_early_v2_| is true. PING frames will be sent as needed to // enforce this. const int64_t kDefaultRetransmittableOnWireTimeoutMillisecs = 100;
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc index 73b3e28..2a26bc8 100644 --- a/net/quic/quic_stream_factory_test.cc +++ b/net/quic/quic_stream_factory_test.cc
@@ -804,6 +804,27 @@ version_.transport_version, n); } + std::string ConstructDataHeader(size_t body_len) { + if (version_.transport_version != quic::QUIC_VERSION_99) { + return ""; + } + quic::HttpEncoder encoder; + std::unique_ptr<char[]> buffer; + auto header_length = encoder.SerializeDataFrameHeader(body_len, &buffer); + return std::string(buffer.get(), header_length); + } + + std::unique_ptr<quic::QuicEncryptedPacket> ConstructServerDataPacket( + uint64_t packet_number, + quic::QuicStreamId stream_id, + bool should_include_version, + bool fin, + quic::QuicStreamOffset offset, + quic::QuicStringPiece data) { + return server_maker_.MakeDataPacket( + packet_number, stream_id, should_include_version, fin, offset, data); + } + quic::QuicStreamId GetNthServerInitiatedUnidirectionalStreamId(int n) { return quic::test::GetNthServerInitiatedUnidirectionalStreamId( version_.transport_version, n); @@ -7207,12 +7228,880 @@ EXPECT_EQ(200, response.headers->response_code()); stream.reset(); + EXPECT_TRUE(socket_data.AllWriteDataConsumed()); + EXPECT_TRUE(socket_data1.AllReadDataConsumed()); + EXPECT_TRUE(socket_data1.AllWriteDataConsumed()); +} + +// This test verifies that when connection migration on path degrading is +// enabled, and no custom retransmittable on wire timeout is specified, the +// default value is used. +TEST_P(QuicStreamFactoryTest, DefaultRetransmittableOnWireTimeoutForMigration) { + InitializeConnectionMigrationV2Test( + {kDefaultNetworkForTests, kNewNetworkForTests}); + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + + // Using a testing task runner. + auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(); + QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), task_runner.get()); + QuicStreamFactoryPeer::SetAlarmFactory( + factory_.get(), + std::make_unique<QuicChromiumAlarmFactory>(task_runner.get(), &clock_)); + + MockQuicData socket_data; + quic::QuicStreamOffset header_stream_offset = 0; + socket_data.AddWrite( + SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset)); + socket_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause + socket_data.AddRead(ASYNC, ERR_ADDRESS_UNREACHABLE); + socket_data.AddSocketDataToFactory(socket_factory_.get()); + + // Set up second socket data provider that is used after + // migration. The request is written to this new socket, and the + // response to the request is read on this new socket. + MockQuicData socket_data1; + // The PING packet sent post migration. + socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(2, true)); + socket_data1.AddWrite( + SYNCHRONOUS, ConstructGetRequestPacket( + 3, GetNthClientInitiatedBidirectionalStreamId(0), true, + true, &header_stream_offset)); + socket_data1.AddRead(ASYNC, ERR_IO_PENDING); // Pause. + // Read two packets so that client will send ACK immedaitely. + spdy::SpdyHeaderBlock response_headers = + server_maker_.GetResponseHeaders("200 OK"); + response_headers["key1"] = std::string(2000, 'A'); + spdy::SpdyHeadersIR headers_frame( + GetNthClientInitiatedBidirectionalStreamId(0), + std::move(response_headers)); + spdy::SpdyFramer response_framer(spdy::SpdyFramer::ENABLE_COMPRESSION); + spdy::SpdySerializedFrame spdy_frame = + response_framer.SerializeFrame(headers_frame); + size_t chunk_size = 1200; + unsigned int packet_number = 1; + for (size_t offset = 0; offset < spdy_frame.size(); offset += chunk_size) { + size_t len = std::min(chunk_size, spdy_frame.size() - offset); + socket_data1.AddRead( + ASYNC, + server_maker_.MakeDataPacket( + packet_number++, + quic::QuicUtils::GetHeadersStreamId(version_.transport_version), + false, false, offset, + base::StringPiece(spdy_frame.data() + offset, len))); + } + // Read an ACK from server which acks all client data. + socket_data1.AddRead(SYNCHRONOUS, + server_maker_.MakeAckPacket(3, 3, 1, 1, false)); + socket_data1.AddWrite(ASYNC, client_maker_.MakeAckPacket(4, 2, 1, 1, false)); + // The PING packet sent for retransmittable on wire. + socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(5, false)); + socket_data1.AddRead(ASYNC, ERR_IO_PENDING); // Pause. + std::string header = ConstructDataHeader(6); + socket_data1.AddRead( + ASYNC, ConstructServerDataPacket( + 3, GetNthClientInitiatedBidirectionalStreamId(0), false, true, + 0, header + "hello!")); + socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read. + socket_data1.AddWrite( + SYNCHRONOUS, client_maker_.MakeRstPacket( + 6, false, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + socket_data1.AddSocketDataToFactory(socket_factory_.get()); + + // Create request and QuicHttpStream. + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request( + host_port_pair_, version_.transport_version, privacy_mode_, + DEFAULT_PRIORITY, SocketTag(), + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + EXPECT_EQ(OK, callback_.WaitForResult()); + std::unique_ptr<HttpStream> stream = CreateStream(&request); + EXPECT_TRUE(stream.get()); + + // Cause QUIC stream to be created. + HttpRequestInfo request_info; + request_info.method = "GET"; + request_info.url = GURL("https://www.example.org/"); + request_info.traffic_annotation = + MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + EXPECT_EQ(OK, stream->InitializeStream(&request_info, true, DEFAULT_PRIORITY, + net_log_, CompletionOnceCallback())); + + // Ensure that session is alive and active. + QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); + EXPECT_TRUE(HasActiveSession(host_port_pair_)); + + // Now notify network is disconnected, cause the migration to complete + // immediately. + scoped_mock_network_change_notifier_->mock_network_change_notifier() + ->NotifyNetworkDisconnected(kDefaultNetworkForTests); + + // Complete migration. + task_runner->RunUntilIdle(); + EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session)); + EXPECT_TRUE(HasActiveSession(host_port_pair_)); + EXPECT_EQ(1u, session->GetNumActiveStreams()); + + // Send GET request on stream. + HttpResponseInfo response; + HttpRequestHeaders request_headers; + EXPECT_EQ(OK, stream->SendRequest(request_headers, &response, + callback_.callback())); + socket_data1.Resume(); + // Spin up the message loop to read incoming data from server till the ACK. + base::RunLoop().RunUntilIdle(); + + // Ack delay time. + int delay = task_runner->NextPendingTaskDelay().InMilliseconds(); + EXPECT_GT(kDefaultRetransmittableOnWireTimeoutMillisecs, delay); + // Fire the ack alarm, since ack has been sent, no ack will be sent. + clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(delay)); + task_runner->FastForwardBy(task_runner->NextPendingTaskDelay()); + + // Fire the ping alarm with retransmittable-on-wire timeout, send PING. + delay = kDefaultRetransmittableOnWireTimeoutMillisecs - delay; + EXPECT_EQ(base::TimeDelta::FromMilliseconds(delay), + task_runner->NextPendingTaskDelay()); + clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(delay)); + task_runner->FastForwardBy(task_runner->NextPendingTaskDelay()); + + socket_data1.Resume(); + + // Verify that response headers on the migrated socket were delivered to the + // stream. + EXPECT_EQ(OK, stream->ReadResponseHeaders(callback_.callback())); + EXPECT_EQ(200, response.headers->response_code()); + + // Resume the old socket data, a read error will be delivered to the old + // packet reader. Verify that the session is not affected. + socket_data.Resume(); + EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session)); + EXPECT_TRUE(HasActiveSession(host_port_pair_)); + EXPECT_EQ(1u, session->GetNumActiveStreams()); + + stream.reset(); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed()); EXPECT_TRUE(socket_data1.AllReadDataConsumed()); EXPECT_TRUE(socket_data1.AllWriteDataConsumed()); } +// This test verifies that when connection migration on path degrading is +// enabled, and a custom retransmittable on wire timeout is specified, the +// custom value is used. +TEST_P(QuicStreamFactoryTest, CustomRetransmittableOnWireTimeoutForMigration) { + int custom_timeout_value = 200; + test_params_.quic_retransmittable_on_wire_timeout_milliseconds = + custom_timeout_value; + InitializeConnectionMigrationV2Test( + {kDefaultNetworkForTests, kNewNetworkForTests}); + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + + // Using a testing task runner. + auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(); + QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), task_runner.get()); + QuicStreamFactoryPeer::SetAlarmFactory( + factory_.get(), + std::make_unique<QuicChromiumAlarmFactory>(task_runner.get(), &clock_)); + + MockQuicData socket_data; + quic::QuicStreamOffset header_stream_offset = 0; + socket_data.AddWrite( + SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset)); + socket_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause + socket_data.AddRead(ASYNC, ERR_ADDRESS_UNREACHABLE); + socket_data.AddSocketDataToFactory(socket_factory_.get()); + + // Set up second socket data provider that is used after + // migration. The request is written to this new socket, and the + // response to the request is read on this new socket. + MockQuicData socket_data1; + // The PING packet sent post migration. + socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(2, true)); + socket_data1.AddWrite( + SYNCHRONOUS, ConstructGetRequestPacket( + 3, GetNthClientInitiatedBidirectionalStreamId(0), true, + true, &header_stream_offset)); + socket_data1.AddRead(ASYNC, ERR_IO_PENDING); // Pause. + // Read two packets so that client will send ACK immedaitely. + spdy::SpdyHeaderBlock response_headers = + server_maker_.GetResponseHeaders("200 OK"); + response_headers["key1"] = std::string(2000, 'A'); + spdy::SpdyHeadersIR headers_frame( + GetNthClientInitiatedBidirectionalStreamId(0), + std::move(response_headers)); + spdy::SpdyFramer response_framer(spdy::SpdyFramer::ENABLE_COMPRESSION); + spdy::SpdySerializedFrame spdy_frame = + response_framer.SerializeFrame(headers_frame); + size_t chunk_size = 1200; + unsigned int packet_number = 1; + for (size_t offset = 0; offset < spdy_frame.size(); offset += chunk_size) { + size_t len = std::min(chunk_size, spdy_frame.size() - offset); + socket_data1.AddRead( + ASYNC, + server_maker_.MakeDataPacket( + packet_number++, + quic::QuicUtils::GetHeadersStreamId(version_.transport_version), + false, false, offset, + base::StringPiece(spdy_frame.data() + offset, len))); + } + // Read an ACK from server which acks all client data. + socket_data1.AddRead(SYNCHRONOUS, + server_maker_.MakeAckPacket(3, 3, 1, 1, false)); + socket_data1.AddWrite(ASYNC, client_maker_.MakeAckPacket(4, 2, 1, 1, false)); + // The PING packet sent for retransmittable on wire. + socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(5, false)); + socket_data1.AddRead(ASYNC, ERR_IO_PENDING); // Pause. + std::string header = ConstructDataHeader(6); + socket_data1.AddRead( + ASYNC, ConstructServerDataPacket( + 3, GetNthClientInitiatedBidirectionalStreamId(0), false, true, + 0, header + "hello!")); + socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read. + socket_data1.AddWrite( + SYNCHRONOUS, client_maker_.MakeRstPacket( + 6, false, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + socket_data1.AddSocketDataToFactory(socket_factory_.get()); + + // Create request and QuicHttpStream. + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request( + host_port_pair_, version_.transport_version, privacy_mode_, + DEFAULT_PRIORITY, SocketTag(), + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + EXPECT_EQ(OK, callback_.WaitForResult()); + std::unique_ptr<HttpStream> stream = CreateStream(&request); + EXPECT_TRUE(stream.get()); + + // Cause QUIC stream to be created. + HttpRequestInfo request_info; + request_info.method = "GET"; + request_info.url = GURL("https://www.example.org/"); + request_info.traffic_annotation = + MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + EXPECT_EQ(OK, stream->InitializeStream(&request_info, true, DEFAULT_PRIORITY, + net_log_, CompletionOnceCallback())); + + // Ensure that session is alive and active. + QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); + EXPECT_TRUE(HasActiveSession(host_port_pair_)); + + // Now notify network is disconnected, cause the migration to complete + // immediately. + scoped_mock_network_change_notifier_->mock_network_change_notifier() + ->NotifyNetworkDisconnected(kDefaultNetworkForTests); + + // Complete migration. + task_runner->RunUntilIdle(); + EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session)); + EXPECT_TRUE(HasActiveSession(host_port_pair_)); + EXPECT_EQ(1u, session->GetNumActiveStreams()); + + // Send GET request on stream. + HttpResponseInfo response; + HttpRequestHeaders request_headers; + EXPECT_EQ(OK, stream->SendRequest(request_headers, &response, + callback_.callback())); + socket_data1.Resume(); + // Spin up the message loop to read incoming data from server till the ACK. + base::RunLoop().RunUntilIdle(); + + // Ack delay time. + int delay = task_runner->NextPendingTaskDelay().InMilliseconds(); + EXPECT_GT(custom_timeout_value, delay); + // Fire the ack alarm, since ack has been sent, no ack will be sent. + clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(delay)); + task_runner->FastForwardBy(task_runner->NextPendingTaskDelay()); + + // Fire the ping alarm with retransmittable-on-wire timeout, send PING. + delay = custom_timeout_value - delay; + EXPECT_EQ(base::TimeDelta::FromMilliseconds(delay), + task_runner->NextPendingTaskDelay()); + clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(delay)); + task_runner->FastForwardBy(task_runner->NextPendingTaskDelay()); + + socket_data1.Resume(); + + // Verify that response headers on the migrated socket were delivered to the + // stream. + EXPECT_EQ(OK, stream->ReadResponseHeaders(callback_.callback())); + EXPECT_EQ(200, response.headers->response_code()); + + // Resume the old socket data, a read error will be delivered to the old + // packet reader. Verify that the session is not affected. + socket_data.Resume(); + EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session)); + EXPECT_TRUE(HasActiveSession(host_port_pair_)); + EXPECT_EQ(1u, session->GetNumActiveStreams()); + + stream.reset(); + EXPECT_TRUE(socket_data.AllReadDataConsumed()); + EXPECT_TRUE(socket_data.AllWriteDataConsumed()); + EXPECT_TRUE(socket_data1.AllReadDataConsumed()); + EXPECT_TRUE(socket_data1.AllWriteDataConsumed()); +} + +// This test verifies that when no migration is enabled, but a custom value for +// retransmittable-on-wire timeout is specified, the ping alarm is set up to +// send retransmittable pings with the custom value. +TEST_P(QuicStreamFactoryTest, CustomRetransmittableOnWireTimeout) { + int custom_timeout_value = 200; + test_params_.quic_retransmittable_on_wire_timeout_milliseconds = + custom_timeout_value; + Initialize(); + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + + // Using a testing task runner. + auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(); + QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), task_runner.get()); + QuicStreamFactoryPeer::SetAlarmFactory( + factory_.get(), + std::make_unique<QuicChromiumAlarmFactory>(task_runner.get(), &clock_)); + + MockQuicData socket_data1; + quic::QuicStreamOffset header_stream_offset = 0; + socket_data1.AddWrite( + SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset)); + socket_data1.AddWrite( + SYNCHRONOUS, ConstructGetRequestPacket( + 2, GetNthClientInitiatedBidirectionalStreamId(0), true, + true, &header_stream_offset)); + socket_data1.AddRead(ASYNC, ERR_IO_PENDING); // Pause. + // Read two packets so that client will send ACK immedaitely. + spdy::SpdyHeaderBlock response_headers = + server_maker_.GetResponseHeaders("200 OK"); + response_headers["key1"] = std::string(2000, 'A'); + spdy::SpdyHeadersIR headers_frame( + GetNthClientInitiatedBidirectionalStreamId(0), + std::move(response_headers)); + spdy::SpdyFramer response_framer(spdy::SpdyFramer::ENABLE_COMPRESSION); + spdy::SpdySerializedFrame spdy_frame = + response_framer.SerializeFrame(headers_frame); + size_t chunk_size = 1200; + unsigned int packet_number = 1; + for (size_t offset = 0; offset < spdy_frame.size(); offset += chunk_size) { + size_t len = std::min(chunk_size, spdy_frame.size() - offset); + socket_data1.AddRead( + ASYNC, + server_maker_.MakeDataPacket( + packet_number++, + quic::QuicUtils::GetHeadersStreamId(version_.transport_version), + false, false, offset, + base::StringPiece(spdy_frame.data() + offset, len))); + } + // Read an ACK from server which acks all client data. + socket_data1.AddRead(SYNCHRONOUS, + server_maker_.MakeAckPacket(3, 2, 1, 1, false)); + socket_data1.AddWrite(ASYNC, client_maker_.MakeAckPacket(3, 2, 1, 1, false)); + // The PING packet sent for retransmittable on wire. + socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(4, false)); + socket_data1.AddRead(ASYNC, ERR_IO_PENDING); // Pause. + std::string header = ConstructDataHeader(6); + socket_data1.AddRead( + ASYNC, ConstructServerDataPacket( + 3, GetNthClientInitiatedBidirectionalStreamId(0), false, true, + 0, header + "hello!")); + socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read. + socket_data1.AddWrite( + SYNCHRONOUS, client_maker_.MakeRstPacket( + 5, false, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + socket_data1.AddSocketDataToFactory(socket_factory_.get()); + + // Create request and QuicHttpStream. + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request( + host_port_pair_, version_.transport_version, privacy_mode_, + DEFAULT_PRIORITY, SocketTag(), + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + EXPECT_EQ(OK, callback_.WaitForResult()); + std::unique_ptr<HttpStream> stream = CreateStream(&request); + EXPECT_TRUE(stream.get()); + + // Cause QUIC stream to be created. + HttpRequestInfo request_info; + request_info.method = "GET"; + request_info.url = GURL("https://www.example.org/"); + request_info.traffic_annotation = + MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + EXPECT_EQ(OK, stream->InitializeStream(&request_info, true, DEFAULT_PRIORITY, + net_log_, CompletionOnceCallback())); + + // Ensure that session is alive and active. + QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); + EXPECT_TRUE(HasActiveSession(host_port_pair_)); + + // Complete migration. + task_runner->RunUntilIdle(); + EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session)); + EXPECT_TRUE(HasActiveSession(host_port_pair_)); + EXPECT_EQ(1u, session->GetNumActiveStreams()); + + // Send GET request on stream. + HttpResponseInfo response; + HttpRequestHeaders request_headers; + EXPECT_EQ(OK, stream->SendRequest(request_headers, &response, + callback_.callback())); + socket_data1.Resume(); + // Spin up the message loop to read incoming data from server till the ACK. + base::RunLoop().RunUntilIdle(); + + // Ack delay time. + int delay = task_runner->NextPendingTaskDelay().InMilliseconds(); + EXPECT_GT(custom_timeout_value, delay); + // Fire the ack alarm, since ack has been sent, no ack will be sent. + clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(delay)); + task_runner->FastForwardBy(task_runner->NextPendingTaskDelay()); + + // Fire the ping alarm with retransmittable-on-wire timeout, send PING. + delay = custom_timeout_value - delay; + EXPECT_EQ(base::TimeDelta::FromMilliseconds(delay), + task_runner->NextPendingTaskDelay()); + clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(delay)); + task_runner->FastForwardBy(task_runner->NextPendingTaskDelay()); + + socket_data1.Resume(); + + // Verify that response headers on the migrated socket were delivered to the + // stream. + EXPECT_EQ(OK, stream->ReadResponseHeaders(callback_.callback())); + EXPECT_EQ(200, response.headers->response_code()); + + // Resume the old socket data, a read error will be delivered to the old + // packet reader. Verify that the session is not affected. + EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session)); + EXPECT_TRUE(HasActiveSession(host_port_pair_)); + EXPECT_EQ(1u, session->GetNumActiveStreams()); + + stream.reset(); + EXPECT_TRUE(socket_data1.AllReadDataConsumed()); + EXPECT_TRUE(socket_data1.AllWriteDataConsumed()); +} + +// This test verifies that when no migration is enabled, and no custom value +// for retransmittable-on-wire timeout is specified, the ping alarm will not +// send any retransmittable pings. +TEST_P(QuicStreamFactoryTest, NoRetransmittableOnWireTimeout) { + Initialize(); + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + + // Using a testing task runner. + auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(); + QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), task_runner.get()); + QuicStreamFactoryPeer::SetAlarmFactory( + factory_.get(), + std::make_unique<QuicChromiumAlarmFactory>(task_runner.get(), &clock_)); + + MockQuicData socket_data1; + quic::QuicStreamOffset header_stream_offset = 0; + socket_data1.AddWrite( + SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset)); + socket_data1.AddWrite( + SYNCHRONOUS, ConstructGetRequestPacket( + 2, GetNthClientInitiatedBidirectionalStreamId(0), true, + true, &header_stream_offset)); + socket_data1.AddRead(ASYNC, ERR_IO_PENDING); // Pause. + // Read two packets so that client will send ACK immedaitely. + spdy::SpdyHeaderBlock response_headers = + server_maker_.GetResponseHeaders("200 OK"); + response_headers["key1"] = std::string(2000, 'A'); + spdy::SpdyHeadersIR headers_frame( + GetNthClientInitiatedBidirectionalStreamId(0), + std::move(response_headers)); + spdy::SpdyFramer response_framer(spdy::SpdyFramer::ENABLE_COMPRESSION); + spdy::SpdySerializedFrame spdy_frame = + response_framer.SerializeFrame(headers_frame); + size_t chunk_size = 1200; + unsigned int packet_number = 1; + for (size_t offset = 0; offset < spdy_frame.size(); offset += chunk_size) { + size_t len = std::min(chunk_size, spdy_frame.size() - offset); + socket_data1.AddRead( + ASYNC, + server_maker_.MakeDataPacket( + packet_number++, + quic::QuicUtils::GetHeadersStreamId(version_.transport_version), + false, false, offset, + base::StringPiece(spdy_frame.data() + offset, len))); + } + // Read an ACK from server which acks all client data. + socket_data1.AddRead(SYNCHRONOUS, + server_maker_.MakeAckPacket(3, 2, 1, 1, false)); + socket_data1.AddWrite(ASYNC, client_maker_.MakeAckPacket(3, 2, 1, 1, false)); + std::string header = ConstructDataHeader(6); + socket_data1.AddRead( + ASYNC, ConstructServerDataPacket( + 3, GetNthClientInitiatedBidirectionalStreamId(0), false, true, + 0, header + "hello!")); + socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read. + socket_data1.AddWrite( + SYNCHRONOUS, client_maker_.MakeRstPacket( + 4, false, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + socket_data1.AddSocketDataToFactory(socket_factory_.get()); + + // Create request and QuicHttpStream. + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request( + host_port_pair_, version_.transport_version, privacy_mode_, + DEFAULT_PRIORITY, SocketTag(), + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + EXPECT_EQ(OK, callback_.WaitForResult()); + std::unique_ptr<HttpStream> stream = CreateStream(&request); + EXPECT_TRUE(stream.get()); + + // Cause QUIC stream to be created. + HttpRequestInfo request_info; + request_info.method = "GET"; + request_info.url = GURL("https://www.example.org/"); + request_info.traffic_annotation = + MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + EXPECT_EQ(OK, stream->InitializeStream(&request_info, true, DEFAULT_PRIORITY, + net_log_, CompletionOnceCallback())); + + // Ensure that session is alive and active. + QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); + EXPECT_TRUE(HasActiveSession(host_port_pair_)); + + // Complete migration. + task_runner->RunUntilIdle(); + EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session)); + EXPECT_TRUE(HasActiveSession(host_port_pair_)); + EXPECT_EQ(1u, session->GetNumActiveStreams()); + + // Send GET request on stream. + HttpResponseInfo response; + HttpRequestHeaders request_headers; + EXPECT_EQ(OK, stream->SendRequest(request_headers, &response, + callback_.callback())); + socket_data1.Resume(); + // Spin up the message loop to read incoming data from server till the ACK. + base::RunLoop().RunUntilIdle(); + + // Ack delay time. + int delay = task_runner->NextPendingTaskDelay().InMilliseconds(); + EXPECT_GT(kDefaultRetransmittableOnWireTimeoutMillisecs, delay); + // Fire the ack alarm, since ack has been sent, no ack will be sent. + clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(delay)); + task_runner->FastForwardBy(task_runner->NextPendingTaskDelay()); + + // Verify that the ping alarm is not set with any default value. + int wrong_delay = kDefaultRetransmittableOnWireTimeoutMillisecs - delay; + delay = task_runner->NextPendingTaskDelay().InMilliseconds(); + EXPECT_NE(wrong_delay, delay); + clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(delay)); + task_runner->FastForwardBy(task_runner->NextPendingTaskDelay()); + + // Verify that response headers on the migrated socket were delivered to the + // stream. + EXPECT_EQ(OK, stream->ReadResponseHeaders(callback_.callback())); + EXPECT_EQ(200, response.headers->response_code()); + + // Resume the old socket data, a read error will be delivered to the old + // packet reader. Verify that the session is not affected. + EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session)); + EXPECT_TRUE(HasActiveSession(host_port_pair_)); + EXPECT_EQ(1u, session->GetNumActiveStreams()); + + stream.reset(); + EXPECT_TRUE(socket_data1.AllReadDataConsumed()); + EXPECT_TRUE(socket_data1.AllWriteDataConsumed()); +} + +// This test verifies that when only migration on network change is enabled, and +// a custom value for retransmittable-on-wire is specified, the ping alarm will +// send retransmittable pings to the peer with custom value. +TEST_P(QuicStreamFactoryTest, + CustomeRetransmittableOnWireTimeoutWithMigrationOnNetworkChangeOnly) { + int custom_timeout_value = 200; + test_params_.quic_retransmittable_on_wire_timeout_milliseconds = + custom_timeout_value; + test_params_.quic_migrate_sessions_on_network_change_v2 = true; + Initialize(); + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + + // Using a testing task runner. + auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(); + QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), task_runner.get()); + QuicStreamFactoryPeer::SetAlarmFactory( + factory_.get(), + std::make_unique<QuicChromiumAlarmFactory>(task_runner.get(), &clock_)); + + MockQuicData socket_data1; + quic::QuicStreamOffset header_stream_offset = 0; + socket_data1.AddWrite( + SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset)); + socket_data1.AddWrite( + SYNCHRONOUS, ConstructGetRequestPacket( + 2, GetNthClientInitiatedBidirectionalStreamId(0), true, + true, &header_stream_offset)); + socket_data1.AddRead(ASYNC, ERR_IO_PENDING); // Pause. + // Read two packets so that client will send ACK immedaitely. + spdy::SpdyHeaderBlock response_headers = + server_maker_.GetResponseHeaders("200 OK"); + response_headers["key1"] = std::string(2000, 'A'); + spdy::SpdyHeadersIR headers_frame( + GetNthClientInitiatedBidirectionalStreamId(0), + std::move(response_headers)); + spdy::SpdyFramer response_framer(spdy::SpdyFramer::ENABLE_COMPRESSION); + spdy::SpdySerializedFrame spdy_frame = + response_framer.SerializeFrame(headers_frame); + size_t chunk_size = 1200; + unsigned int packet_number = 1; + for (size_t offset = 0; offset < spdy_frame.size(); offset += chunk_size) { + size_t len = std::min(chunk_size, spdy_frame.size() - offset); + socket_data1.AddRead( + ASYNC, + server_maker_.MakeDataPacket( + packet_number++, + quic::QuicUtils::GetHeadersStreamId(version_.transport_version), + false, false, offset, + base::StringPiece(spdy_frame.data() + offset, len))); + } + // Read an ACK from server which acks all client data. + socket_data1.AddRead(SYNCHRONOUS, + server_maker_.MakeAckPacket(3, 2, 1, 1, false)); + socket_data1.AddWrite(ASYNC, client_maker_.MakeAckPacket(3, 2, 1, 1, false)); + // The PING packet sent for retransmittable on wire. + socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakePingPacket(4, false)); + socket_data1.AddRead(ASYNC, ERR_IO_PENDING); // Pause. + std::string header = ConstructDataHeader(6); + socket_data1.AddRead( + ASYNC, ConstructServerDataPacket( + 3, GetNthClientInitiatedBidirectionalStreamId(0), false, true, + 0, header + "hello!")); + socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read. + socket_data1.AddWrite( + SYNCHRONOUS, client_maker_.MakeRstPacket( + 5, false, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + socket_data1.AddSocketDataToFactory(socket_factory_.get()); + + // Create request and QuicHttpStream. + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request( + host_port_pair_, version_.transport_version, privacy_mode_, + DEFAULT_PRIORITY, SocketTag(), + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + EXPECT_EQ(OK, callback_.WaitForResult()); + std::unique_ptr<HttpStream> stream = CreateStream(&request); + EXPECT_TRUE(stream.get()); + + // Cause QUIC stream to be created. + HttpRequestInfo request_info; + request_info.method = "GET"; + request_info.url = GURL("https://www.example.org/"); + request_info.traffic_annotation = + MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + EXPECT_EQ(OK, stream->InitializeStream(&request_info, true, DEFAULT_PRIORITY, + net_log_, CompletionOnceCallback())); + + // Ensure that session is alive and active. + QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); + EXPECT_TRUE(HasActiveSession(host_port_pair_)); + + // Complete migration. + task_runner->RunUntilIdle(); + EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session)); + EXPECT_TRUE(HasActiveSession(host_port_pair_)); + EXPECT_EQ(1u, session->GetNumActiveStreams()); + + // Send GET request on stream. + HttpResponseInfo response; + HttpRequestHeaders request_headers; + EXPECT_EQ(OK, stream->SendRequest(request_headers, &response, + callback_.callback())); + socket_data1.Resume(); + // Spin up the message loop to read incoming data from server till the ACK. + base::RunLoop().RunUntilIdle(); + + // Ack delay time. + int delay = task_runner->NextPendingTaskDelay().InMilliseconds(); + EXPECT_GT(custom_timeout_value, delay); + // Fire the ack alarm, since ack has been sent, no ack will be sent. + clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(delay)); + task_runner->FastForwardBy(task_runner->NextPendingTaskDelay()); + + // Fire the ping alarm with retransmittable-on-wire timeout, send PING. + delay = custom_timeout_value - delay; + EXPECT_EQ(base::TimeDelta::FromMilliseconds(delay), + task_runner->NextPendingTaskDelay()); + clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(delay)); + task_runner->FastForwardBy(task_runner->NextPendingTaskDelay()); + + socket_data1.Resume(); + + // Verify that response headers on the migrated socket were delivered to the + // stream. + EXPECT_EQ(OK, stream->ReadResponseHeaders(callback_.callback())); + EXPECT_EQ(200, response.headers->response_code()); + + // Resume the old socket data, a read error will be delivered to the old + // packet reader. Verify that the session is not affected. + EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session)); + EXPECT_TRUE(HasActiveSession(host_port_pair_)); + EXPECT_EQ(1u, session->GetNumActiveStreams()); + + stream.reset(); + EXPECT_TRUE(socket_data1.AllReadDataConsumed()); + EXPECT_TRUE(socket_data1.AllWriteDataConsumed()); +} + +// This test verifies that when only migration on network change is enabled, and +// no custom value for retransmittable-on-wire is specified, the ping alarm will +// NOT send retransmittable pings to the peer with custom value. +TEST_P(QuicStreamFactoryTest, + NoRetransmittableOnWireTimeoutWithMigrationOnNetworkChangeOnly) { + test_params_.quic_migrate_sessions_on_network_change_v2 = true; + Initialize(); + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + + // Using a testing task runner. + auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(); + QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), task_runner.get()); + QuicStreamFactoryPeer::SetAlarmFactory( + factory_.get(), + std::make_unique<QuicChromiumAlarmFactory>(task_runner.get(), &clock_)); + + MockQuicData socket_data1; + quic::QuicStreamOffset header_stream_offset = 0; + socket_data1.AddWrite( + SYNCHRONOUS, ConstructInitialSettingsPacket(1, &header_stream_offset)); + socket_data1.AddWrite( + SYNCHRONOUS, ConstructGetRequestPacket( + 2, GetNthClientInitiatedBidirectionalStreamId(0), true, + true, &header_stream_offset)); + socket_data1.AddRead(ASYNC, ERR_IO_PENDING); // Pause. + // Read two packets so that client will send ACK immedaitely. + spdy::SpdyHeaderBlock response_headers = + server_maker_.GetResponseHeaders("200 OK"); + response_headers["key1"] = std::string(2000, 'A'); + spdy::SpdyHeadersIR headers_frame( + GetNthClientInitiatedBidirectionalStreamId(0), + std::move(response_headers)); + spdy::SpdyFramer response_framer(spdy::SpdyFramer::ENABLE_COMPRESSION); + spdy::SpdySerializedFrame spdy_frame = + response_framer.SerializeFrame(headers_frame); + size_t chunk_size = 1200; + unsigned int packet_number = 1; + for (size_t offset = 0; offset < spdy_frame.size(); offset += chunk_size) { + size_t len = std::min(chunk_size, spdy_frame.size() - offset); + socket_data1.AddRead( + ASYNC, + server_maker_.MakeDataPacket( + packet_number++, + quic::QuicUtils::GetHeadersStreamId(version_.transport_version), + false, false, offset, + base::StringPiece(spdy_frame.data() + offset, len))); + } + // Read an ACK from server which acks all client data. + socket_data1.AddRead(SYNCHRONOUS, + server_maker_.MakeAckPacket(3, 2, 1, 1, false)); + socket_data1.AddWrite(ASYNC, client_maker_.MakeAckPacket(3, 2, 1, 1, false)); + std::string header = ConstructDataHeader(6); + socket_data1.AddRead( + ASYNC, ConstructServerDataPacket( + 3, GetNthClientInitiatedBidirectionalStreamId(0), false, true, + 0, header + "hello!")); + socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more data to read. + socket_data1.AddWrite( + SYNCHRONOUS, client_maker_.MakeRstPacket( + 4, false, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + socket_data1.AddSocketDataToFactory(socket_factory_.get()); + + // Create request and QuicHttpStream. + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request( + host_port_pair_, version_.transport_version, privacy_mode_, + DEFAULT_PRIORITY, SocketTag(), + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + EXPECT_EQ(OK, callback_.WaitForResult()); + std::unique_ptr<HttpStream> stream = CreateStream(&request); + EXPECT_TRUE(stream.get()); + + // Cause QUIC stream to be created. + HttpRequestInfo request_info; + request_info.method = "GET"; + request_info.url = GURL("https://www.example.org/"); + request_info.traffic_annotation = + MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); + EXPECT_EQ(OK, stream->InitializeStream(&request_info, true, DEFAULT_PRIORITY, + net_log_, CompletionOnceCallback())); + + // Ensure that session is alive and active. + QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); + EXPECT_TRUE(HasActiveSession(host_port_pair_)); + + // Complete migration. + task_runner->RunUntilIdle(); + EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session)); + EXPECT_TRUE(HasActiveSession(host_port_pair_)); + EXPECT_EQ(1u, session->GetNumActiveStreams()); + + // Send GET request on stream. + HttpResponseInfo response; + HttpRequestHeaders request_headers; + EXPECT_EQ(OK, stream->SendRequest(request_headers, &response, + callback_.callback())); + socket_data1.Resume(); + // Spin up the message loop to read incoming data from server till the ACK. + base::RunLoop().RunUntilIdle(); + + // Ack delay time. + int delay = task_runner->NextPendingTaskDelay().InMilliseconds(); + EXPECT_GT(kDefaultRetransmittableOnWireTimeoutMillisecs, delay); + // Fire the ack alarm, since ack has been sent, no ack will be sent. + clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(delay)); + task_runner->FastForwardBy(task_runner->NextPendingTaskDelay()); + + // Verify ping alarm is not set with default value. + int wrong_delay = kDefaultRetransmittableOnWireTimeoutMillisecs - delay; + delay = task_runner->NextPendingTaskDelay().InMilliseconds(); + EXPECT_NE(wrong_delay, delay); + clock_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(delay)); + task_runner->FastForwardBy(task_runner->NextPendingTaskDelay()); + + // Verify that response headers on the migrated socket were delivered to the + // stream. + EXPECT_EQ(OK, stream->ReadResponseHeaders(callback_.callback())); + EXPECT_EQ(200, response.headers->response_code()); + + // Resume the old socket data, a read error will be delivered to the old + // packet reader. Verify that the session is not affected. + EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session)); + EXPECT_TRUE(HasActiveSession(host_port_pair_)); + EXPECT_EQ(1u, session->GetNumActiveStreams()); + + stream.reset(); + EXPECT_TRUE(socket_data1.AllReadDataConsumed()); + EXPECT_TRUE(socket_data1.AllWriteDataConsumed()); +} + // This test verifies that after migration on write error is posted, packet // read error on the old reader will be ignored and will not close the // connection.
diff --git a/printing/backend/cups_helper.cc b/printing/backend/cups_helper.cc index 9fff0c5b..e522d6c 100644 --- a/printing/backend/cups_helper.cc +++ b/printing/backend/cups_helper.cc
@@ -66,9 +66,8 @@ const size_t kDestLen = sizeof(kDest) - 1; const size_t kDefaultLen = sizeof(kDefault) - 1; - for (base::StringPiece line : - base::SplitStringPiece(content, "\n", base::KEEP_WHITESPACE, - base::SPLIT_WANT_NONEMPTY)) { + for (base::StringPiece line : base::SplitStringPiece( + content, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { if (base::StartsWith(line, base::StringPiece(kDefault, kDefaultLen), base::CompareCase::INSENSITIVE_ASCII) && isspace(line[kDefaultLen])) { @@ -235,8 +234,8 @@ // value. ppd_choice_t* printout_mode_choice = ppdFindMarkedChoice(ppd, kPrintoutMode); if (!printout_mode_choice) { - printout_mode_choice = ppdFindChoice(printout_mode, - printout_mode->defchoice); + printout_mode_choice = + ppdFindChoice(printout_mode, printout_mode->defchoice); } if (printout_mode_choice) { if (EqualsCaseInsensitiveASCII(printout_mode_choice->choice, kNormalGray) || @@ -270,8 +269,8 @@ ppd_choice_t* mode_choice = ppdFindMarkedChoice(ppd, kColorMode); if (!mode_choice) { - mode_choice = ppdFindChoice(color_mode_option, - color_mode_option->defchoice); + mode_choice = + ppdFindChoice(color_mode_option, color_mode_option->defchoice); } if (mode_choice) { @@ -333,8 +332,8 @@ ppd_choice_t* mode_choice = ppdFindMarkedChoice(ppd, kColorMode); if (!mode_choice) { - mode_choice = ppdFindChoice(color_mode_option, - color_mode_option->defchoice); + mode_choice = + ppdFindChoice(color_mode_option, color_mode_option->defchoice); } if (mode_choice) { *color_is_default = EqualsCaseInsensitiveASCII(mode_choice->choice, kColor); @@ -347,7 +346,7 @@ ColorModel* color_model_for_color, bool* color_is_default) { // Canon printers use "ProcessColorModel" attribute in their PPDs. - ppd_option_t* color_mode_option = ppdFindOption(ppd, kProcessColorModel); + ppd_option_t* color_mode_option = ppdFindOption(ppd, kProcessColorModel); if (!color_mode_option) return false; @@ -361,8 +360,8 @@ ppd_choice_t* mode_choice = ppdFindMarkedChoice(ppd, kProcessColorModel); if (!mode_choice) { - mode_choice = ppdFindChoice(color_mode_option, - color_mode_option->defchoice); + mode_choice = + ppdFindChoice(color_mode_option, color_mode_option->defchoice); } if (mode_choice) { @@ -422,7 +421,7 @@ } void HttpConnectionCUPS::SetBlocking(bool blocking) { - httpBlocking(http_, blocking ? 1 : 0); + httpBlocking(http_, blocking ? 1 : 0); } http_t* HttpConnectionCUPS::http() { @@ -437,10 +436,8 @@ return false; int data_size = printer_capabilities.length(); - if (data_size != base::WriteFile( - ppd_file_path, - printer_capabilities.data(), - data_size)) { + if (data_size != + base::WriteFile(ppd_file_path, printer_capabilities.data(), data_size)) { base::DeleteFile(ppd_file_path, false); return false; } @@ -469,9 +466,9 @@ VLOG(1) << "Unknown printer color model"; } - caps.color_changeable = ((cm_color != UNKNOWN_COLOR_MODEL) && - (cm_black != UNKNOWN_COLOR_MODEL) && - (cm_color != cm_black)); + caps.color_changeable = + ((cm_color != UNKNOWN_COLOR_MODEL) && (cm_black != UNKNOWN_COLOR_MODEL) && + (cm_color != cm_black)); caps.color_default = is_color; caps.color_model = cm_color; caps.bw_model = cm_black;
diff --git a/printing/backend/cups_ipp_util.cc b/printing/backend/cups_ipp_util.cc index f75318b9..7c5aab2 100644 --- a/printing/backend/cups_ipp_util.cc +++ b/printing/backend/cups_ipp_util.cc
@@ -29,8 +29,8 @@ constexpr char kIppColor[] = CUPS_PRINT_COLOR_MODE; constexpr char kIppMedia[] = CUPS_MEDIA; constexpr char kIppDuplex[] = CUPS_SIDES; -constexpr char kIppResolution[] = "printer-resolution"; // RFC 2911 -constexpr char kIppDocumentName[] = "document-name"; // RFC 8011 +constexpr char kIppResolution[] = "printer-resolution"; // RFC 2911 +constexpr char kIppDocumentName[] = "document-name"; // RFC 8011 constexpr char kIppRequestingUserName[] = "requesting-user-name"; // RFC 8011 constexpr char kIppPin[] = "job-password"; // PWG 5100.11 constexpr char kIppPinEncryption[] = "job-password-encryption"; // PWG 5100.11
diff --git a/printing/backend/cups_jobs.cc b/printing/backend/cups_jobs.cc index 31f6d75..80d4763 100644 --- a/printing/backend/cups_jobs.cc +++ b/printing/backend/cups_jobs.cc
@@ -435,7 +435,6 @@ const std::string& resource, bool encrypted, PrinterInfo* printer_info) { - ScopedHttpPtr http = ScopedHttpPtr(httpConnect2( address.c_str(), port, nullptr, AF_INET, encrypted ? HTTP_ENCRYPTION_ALWAYS : HTTP_ENCRYPTION_IF_REQUESTED, 0, @@ -470,7 +469,6 @@ bool GetPrinterStatus(http_t* http, const std::string& printer_id, PrinterStatus* printer_status) { - ipp_status_t status; const std::string printer_uri = PrinterUriFromName(printer_id);
diff --git a/printing/backend/cups_printer.cc b/printing/backend/cups_printer.cc index 07b91fff..2fe9da8 100644 --- a/printing/backend/cups_printer.cc +++ b/printing/backend/cups_printer.cc
@@ -108,8 +108,8 @@ if (state) base::StringToInt(state, &printer_info->printer_status); - const char* drv_info = cupsGetOption(kDriverNameTagName, - printer->num_options, printer->options); + const char* drv_info = + cupsGetOption(kDriverNameTagName, printer->num_options, printer->options); if (drv_info) printer_info->options[kDriverInfoTagName] = *drv_info; @@ -127,9 +127,8 @@ } std::string CupsPrinter::GetMakeAndModel() const { - const char* make_and_model = - cupsGetOption(kDriverNameTagName, destination_->num_options, - destination_->options); + const char* make_and_model = cupsGetOption( + kDriverNameTagName, destination_->num_options, destination_->options); return make_and_model ? std::string(make_and_model) : std::string(); }
diff --git a/printing/backend/print_backend.h b/printing/backend/print_backend.h index f729a7b..a01e8bd 100644 --- a/printing/backend/print_backend.h +++ b/printing/backend/print_backend.h
@@ -121,8 +121,7 @@ #endif // !defined(OS_CHROMEOS) // Gets the information about driver for a specific printer. - virtual std::string GetPrinterDriverInfo( - const std::string& printer_name) = 0; + virtual std::string GetPrinterDriverInfo(const std::string& printer_name) = 0; // Returns true if printer_name points to a valid printer. virtual bool IsValidPrinter(const std::string& printer_name) = 0;
diff --git a/printing/backend/print_backend_consts.cc b/printing/backend/print_backend_consts.cc index 34b6a7e..f843ac0 100644 --- a/printing/backend/print_backend_consts.cc +++ b/printing/backend/print_backend_consts.cc
@@ -12,6 +12,6 @@ const char kCUPSPrintServerURL[] = "print_server_url"; const char kDriverInfoTagName[] = "system_driverinfo"; const char kDriverNameTagName[] = "printer-make-and-model"; // Match CUPS. -const char kLocationTagName[] = "printer-location"; // Match CUPS. +const char kLocationTagName[] = "printer-location"; // Match CUPS. const char kValueFalse[] = "false"; const char kValueTrue[] = "true";
diff --git a/printing/backend/print_backend_cups.cc b/printing/backend/print_backend_cups.cc index 4f7df1e0..8016c15 100644 --- a/printing/backend/print_backend_cups.cc +++ b/printing/backend/print_backend_cups.cc
@@ -55,8 +55,8 @@ if (state) base::StringToInt(state, &printer_info->printer_status); - const char* drv_info = cupsGetOption(kDriverNameTagName, - printer.num_options, printer.options); + const char* drv_info = + cupsGetOption(kDriverNameTagName, printer.num_options, printer.options); if (drv_info) printer_info->options[kDriverInfoTagName] = *drv_info; @@ -75,8 +75,7 @@ bool blocking) : print_server_url_(print_server_url), cups_encryption_(encryption), - blocking_(blocking) { -} + blocking_(blocking) {} bool PrintBackendCUPS::EnumeratePrinters(PrinterList* printer_list) { DCHECK(printer_list); @@ -132,11 +131,11 @@ const std::string& printer_name, PrinterSemanticCapsAndDefaults* printer_info) { PrinterCapsAndDefaults info; - if (!GetPrinterCapsAndDefaults(printer_name, &info) ) + if (!GetPrinterCapsAndDefaults(printer_name, &info)) return false; - return ParsePpdCapabilities( - printer_name, info.printer_capabilities, printer_info); + return ParsePpdCapabilities(printer_name, info.printer_capabilities, + printer_info); } bool PrintBackendCUPS::GetPrinterCapsAndDefaults( @@ -204,8 +203,7 @@ print_backend_settings->GetString(kCUPSPrintServerURL, &print_server_url_str); - print_backend_settings->GetString(kCUPSBlocking, - &cups_blocking); + print_backend_settings->GetString(kCUPSBlocking, &cups_blocking); print_backend_settings->GetInteger(kCUPSEncryption, &encryption); }
diff --git a/printing/backend/print_backend_dummy.cc b/printing/backend/print_backend_dummy.cc index 727bdfa..ee1f4c4 100644 --- a/printing/backend/print_backend_dummy.cc +++ b/printing/backend/print_backend_dummy.cc
@@ -16,16 +16,11 @@ class DummyPrintBackend : public PrintBackend { public: - DummyPrintBackend() { - } + DummyPrintBackend() {} - bool EnumeratePrinters(PrinterList* printer_list) override { - return false; - } + bool EnumeratePrinters(PrinterList* printer_list) override { return false; } - std::string GetDefaultPrinterName() override { - return std::string(); - } + std::string GetDefaultPrinterName() override { return std::string(); } bool GetPrinterBasicInfo(const std::string& printer_name, PrinterBasicInfo* printer_info) override { @@ -44,8 +39,7 @@ return false; } - std::string GetPrinterDriverInfo( - const std::string& printer_name) override { + std::string GetPrinterDriverInfo(const std::string& printer_name) override { return std::string(); }
diff --git a/printing/backend/print_backend_win.cc b/printing/backend/print_backend_win.cc index 3b74abd8..ff497ad 100644 --- a/printing/backend/print_backend_win.cc +++ b/printing/backend/print_backend_win.cc
@@ -170,11 +170,9 @@ bool GetPrinterSemanticCapsAndDefaults( const std::string& printer_name, PrinterSemanticCapsAndDefaults* printer_info) override; - bool GetPrinterCapsAndDefaults( - const std::string& printer_name, - PrinterCapsAndDefaults* printer_info) override; - std::string GetPrinterDriverInfo( - const std::string& printer_name) override; + bool GetPrinterCapsAndDefaults(const std::string& printer_name, + PrinterCapsAndDefaults* printer_info) override; + std::string GetPrinterDriverInfo(const std::string& printer_name) override; bool IsValidPrinter(const std::string& printer_name) override; protected: @@ -262,17 +260,17 @@ if (user_settings->dmFields & DM_DUPLEX) { switch (user_settings->dmDuplex) { - case DMDUP_SIMPLEX: - caps.duplex_default = SIMPLEX; - break; - case DMDUP_VERTICAL: - caps.duplex_default = LONG_EDGE; - break; - case DMDUP_HORIZONTAL: - caps.duplex_default = SHORT_EDGE; - break; - default: - NOTREACHED(); + case DMDUP_SIMPLEX: + caps.duplex_default = SIMPLEX; + break; + case DMDUP_VERTICAL: + caps.duplex_default = LONG_EDGE; + break; + case DMDUP_HORIZONTAL: + caps.duplex_default = SHORT_EDGE; + break; + default: + NOTREACHED(); } }
diff --git a/printing/backend/printing_info_win.cc b/printing/backend/printing_info_win.cc index ab878c0..6dd01ef 100644 --- a/printing/backend/printing_info_win.cc +++ b/printing/backend/printing_info_win.cc
@@ -30,15 +30,15 @@ DWORD size = 0; ::GetPrinter(printer, level, NULL, 0, &size); if (size == 0) { - LOG(WARNING) << "Failed to get size of PRINTER_INFO_" << level << - ", error = " << GetLastError(); + LOG(WARNING) << "Failed to get size of PRINTER_INFO_" << level + << ", error = " << GetLastError(); return NULL; } std::unique_ptr<uint8_t[]> buffer(new uint8_t[size]); memset(buffer.get(), 0, size); if (!::GetPrinter(printer, level, buffer.get(), size, &size)) { - LOG(WARNING) << "Failed to get PRINTER_INFO_" << level << - ", error = " << GetLastError(); + LOG(WARNING) << "Failed to get PRINTER_INFO_" << level + << ", error = " << GetLastError(); return NULL; } return buffer.release();
diff --git a/printing/backend/win_helper.cc b/printing/backend/win_helper.cc index 57951dc..a8c10f8 100644 --- a/printing/backend/win_helper.cc +++ b/printing/backend/win_helper.cc
@@ -27,23 +27,23 @@ namespace { -typedef HRESULT (WINAPI* PTOpenProviderProc)(PCWSTR printer_name, - DWORD version, - HPTPROVIDER* provider); +typedef HRESULT(WINAPI* PTOpenProviderProc)(PCWSTR printer_name, + DWORD version, + HPTPROVIDER* provider); -typedef HRESULT (WINAPI* PTGetPrintCapabilitiesProc)(HPTPROVIDER provider, - IStream* print_ticket, - IStream* capabilities, - BSTR* error_message); +typedef HRESULT(WINAPI* PTGetPrintCapabilitiesProc)(HPTPROVIDER provider, + IStream* print_ticket, + IStream* capabilities, + BSTR* error_message); -typedef HRESULT (WINAPI* PTConvertDevModeToPrintTicketProc)( +typedef HRESULT(WINAPI* PTConvertDevModeToPrintTicketProc)( HPTPROVIDER provider, ULONG devmode_size_in_bytes, PDEVMODE devmode, EPrintTicketScope scope, IStream* print_ticket); -typedef HRESULT (WINAPI* PTConvertPrintTicketToDevModeProc)( +typedef HRESULT(WINAPI* PTConvertPrintTicketToDevModeProc)( HPTPROVIDER provider, IStream* print_ticket, EDefaultDevmodeType base_devmode_type, @@ -52,7 +52,7 @@ PDEVMODE* devmode, BSTR* error_message); -typedef HRESULT (WINAPI* PTMergeAndValidatePrintTicketProc)( +typedef HRESULT(WINAPI* PTMergeAndValidatePrintTicketProc)( HPTPROVIDER provider, IStream* base_ticket, IStream* delta_ticket, @@ -60,11 +60,11 @@ IStream* result_ticket, BSTR* error_message); -typedef HRESULT (WINAPI* PTReleaseMemoryProc)(PVOID buffer); +typedef HRESULT(WINAPI* PTReleaseMemoryProc)(PVOID buffer); -typedef HRESULT (WINAPI* PTCloseProviderProc)(HPTPROVIDER provider); +typedef HRESULT(WINAPI* PTCloseProviderProc)(HPTPROVIDER provider); -typedef HRESULT (WINAPI* StartXpsPrintJobProc)( +typedef HRESULT(WINAPI* StartXpsPrintJobProc)( const LPCWSTR printer_name, const LPCWSTR job_name, const LPCWSTR output_file_name, @@ -107,26 +107,26 @@ } const char kXpsTicketTemplate[] = - "<?xml version='1.0' encoding='UTF-8'?>" - "<psf:PrintTicket " - "xmlns:psf='" - "http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework' " - "xmlns:psk=" - "'http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords' " - "version='1'>" - "<psf:Feature name='psk:PageOutputColor'>" - "<psf:Option name='psk:%s'>" - "</psf:Option>" - "</psf:Feature>" - "</psf:PrintTicket>"; + "<?xml version='1.0' encoding='UTF-8'?>" + "<psf:PrintTicket " + "xmlns:psf='" + "http://schemas.microsoft.com/windows/2003/08/printing/" + "printschemaframework' " + "xmlns:psk=" + "'http://schemas.microsoft.com/windows/2003/08/printing/" + "printschemakeywords' " + "version='1'>" + "<psf:Feature name='psk:PageOutputColor'>" + "<psf:Option name='psk:%s'>" + "</psf:Option>" + "</psf:Feature>" + "</psf:PrintTicket>"; const char kXpsTicketColor[] = "Color"; const char kXpsTicketMonochrome[] = "Monochrome"; - } // namespace - namespace printing { bool XPSModule::Init() { @@ -171,16 +171,14 @@ NOTREACHED(); return false; } - g_release_memory_proc = - reinterpret_cast<PTReleaseMemoryProc>( - GetProcAddress(prntvpt_module, "PTReleaseMemory")); + g_release_memory_proc = reinterpret_cast<PTReleaseMemoryProc>( + GetProcAddress(prntvpt_module, "PTReleaseMemory")); if (!g_release_memory_proc) { NOTREACHED(); return false; } - g_close_provider_proc = - reinterpret_cast<PTCloseProviderProc>( - GetProcAddress(prntvpt_module, "PTCloseProvider")); + g_close_provider_proc = reinterpret_cast<PTCloseProviderProc>( + GetProcAddress(prntvpt_module, "PTCloseProvider")); if (!g_close_provider_proc) { NOTREACHED(); return false; @@ -198,9 +196,7 @@ IStream* print_ticket, IStream* capabilities, BSTR* error_message) { - return g_get_print_capabilities_proc(provider, - print_ticket, - capabilities, + return g_get_print_capabilities_proc(provider, print_ticket, capabilities, error_message); } @@ -209,11 +205,8 @@ PDEVMODE devmode, EPrintTicketScope scope, IStream* print_ticket) { - return g_convert_devmode_to_print_ticket_proc(provider, - devmode_size_in_bytes, - devmode, - scope, - print_ticket); + return g_convert_devmode_to_print_ticket_proc(provider, devmode_size_in_bytes, + devmode, scope, print_ticket); } HRESULT XPSModule::ConvertPrintTicketToDevMode( @@ -224,13 +217,9 @@ ULONG* devmode_byte_count, PDEVMODE* devmode, BSTR* error_message) { - return g_convert_print_ticket_to_devmode_proc(provider, - print_ticket, - base_devmode_type, - scope, - devmode_byte_count, - devmode, - error_message); + return g_convert_print_ticket_to_devmode_proc( + provider, print_ticket, base_devmode_type, scope, devmode_byte_count, + devmode, error_message); } HRESULT XPSModule::MergeAndValidatePrintTicket(HPTPROVIDER provider, @@ -239,12 +228,8 @@ EPrintTicketScope scope, IStream* result_ticket, BSTR* error_message) { - return g_merge_and_validate_print_ticket_proc(provider, - base_ticket, - delta_ticket, - scope, - result_ticket, - error_message); + return g_merge_and_validate_print_ticket_proc( + provider, base_ticket, delta_ticket, scope, result_ticket, error_message); } HRESULT XPSModule::ReleaseMemory(PVOID buffer) { @@ -316,16 +301,10 @@ IXpsPrintJob** xps_print_job, IXpsPrintJobStream** document_stream, IXpsPrintJobStream** print_ticket_stream) { - return g_start_xps_print_job_proc(printer_name, - job_name, - output_file_name, - progress_event, - completion_event, - printable_pages_on, - printable_pages_on_count, - xps_print_job, - document_stream, - print_ticket_stream); + return g_start_xps_print_job_proc( + printer_name, job_name, output_file_name, progress_event, + completion_event, printable_pages_on, printable_pages_on_count, + xps_print_job, document_stream, print_ticket_stream); } bool InitBasicPrinterInfo(HANDLE printer, PrinterBasicInfo* printer_info) {
diff --git a/printing/backend/win_helper.h b/printing/backend/win_helper.h index f31dc67d..c9f1b95 100644 --- a/printing/backend/win_helper.h +++ b/printing/backend/win_helper.h
@@ -33,19 +33,15 @@ class PrinterHandleTraits { public: - typedef HANDLE Handle; + using Handle = HANDLE; static bool CloseHandle(HANDLE handle) { return ::ClosePrinter(handle) != FALSE; } - static bool IsHandleValid(HANDLE handle) { - return handle != NULL; - } + static bool IsHandleValid(HANDLE handle) { return handle != NULL; } - static HANDLE NullHandle() { - return NULL; - } + static HANDLE NullHandle() { return NULL; } private: DISALLOW_IMPLICIT_CONSTRUCTORS(PrinterHandleTraits); @@ -65,34 +61,30 @@ } private: - typedef base::win::GenericScopedHandle<PrinterHandleTraits, - base::win::DummyVerifierTraits> Base; + using Base = base::win::GenericScopedHandle<PrinterHandleTraits, + base::win::DummyVerifierTraits>; }; class PrinterChangeHandleTraits { public: - typedef HANDLE Handle; + using Handle = HANDLE; static bool CloseHandle(HANDLE handle) { ::FindClosePrinterChangeNotification(handle); return true; } - static bool IsHandleValid(HANDLE handle) { - return handle != NULL; - } + static bool IsHandleValid(HANDLE handle) { return handle != NULL; } - static HANDLE NullHandle() { - return NULL; - } + static HANDLE NullHandle() { return NULL; } private: DISALLOW_IMPLICIT_CONSTRUCTORS(PrinterChangeHandleTraits); }; -typedef base::win::GenericScopedHandle<PrinterChangeHandleTraits, - base::win::DummyVerifierTraits> - ScopedPrinterChangeHandle; +using ScopedPrinterChangeHandle = + base::win::GenericScopedHandle<PrinterChangeHandleTraits, + base::win::DummyVerifierTraits>; // Wrapper class to wrap the XPS APIs (PTxxx APIs). This is needed because these // APIs are not available by default on XP. We could delayload prntvpt.dll but @@ -134,7 +126,7 @@ static HRESULT CloseProvider(HPTPROVIDER provider); private: - XPSModule() { } + XPSModule() {} static bool InitImpl(); }; @@ -160,19 +152,19 @@ // All the other methods can ONLY be called after a successful call to Init. // Init can be called many times and by multiple threads. static bool Init(); - static HRESULT StartXpsPrintJob( - const LPCWSTR printer_name, - const LPCWSTR job_name, - const LPCWSTR output_file_name, - HANDLE progress_event, - HANDLE completion_event, - UINT8* printable_pages_on, - UINT32 printable_pages_on_count, - IXpsPrintJob **xps_print_job, - IXpsPrintJobStream **document_stream, - IXpsPrintJobStream **print_ticket_stream); + static HRESULT StartXpsPrintJob(const LPCWSTR printer_name, + const LPCWSTR job_name, + const LPCWSTR output_file_name, + HANDLE progress_event, + HANDLE completion_event, + UINT8* printable_pages_on, + UINT32 printable_pages_on_count, + IXpsPrintJob** xps_print_job, + IXpsPrintJobStream** document_stream, + IXpsPrintJobStream** print_ticket_stream); + private: - XPSPrintModule() { } + XPSPrintModule() {} static bool InitImpl(); };
diff --git a/printing/emf_win.cc b/printing/emf_win.cc index edf6d3c..92b032e 100644 --- a/printing/emf_win.cc +++ b/printing/emf_win.cc
@@ -25,7 +25,9 @@ namespace { -bool DIBFormatNativelySupported(HDC dc, uint32_t escape, const BYTE* bits, +bool DIBFormatNativelySupported(HDC dc, + uint32_t escape, + const BYTE* bits, int size) { BOOL supported = FALSE; if (ExtEscape(dc, QUERYESCSUPPORT, sizeof(escape), @@ -114,9 +116,7 @@ gfx::Rect bound = GetPageBounds(1); RECT rect = bound.ToRECT(); return bound.IsEmpty() || - EnumEnhMetaFile(context, - emf_, - &Emf::SafePlaybackProc, + EnumEnhMetaFile(context, emf_, &Emf::SafePlaybackProc, reinterpret_cast<void*>(&playback_context), &rect) != 0; } @@ -131,8 +131,7 @@ } // Add 1 to right and bottom because it's inclusive rectangle. // See ENHMETAHEADER. - return gfx::Rect(header.rclBounds.left, - header.rclBounds.top, + return gfx::Rect(header.rclBounds.left, header.rclBounds.top, header.rclBounds.right - header.rclBounds.left + 1, header.rclBounds.bottom - header.rclBounds.top + 1); } @@ -179,16 +178,13 @@ memset(this, 0, sizeof(*this)); } -Emf::Record::Record(const ENHMETARECORD* record) - : record_(record) { +Emf::Record::Record(const ENHMETARECORD* record) : record_(record) { DCHECK(record_); } bool Emf::Record::Play(Emf::EnumerationContext* context) const { - return 0 != PlayEnhMetaFileRecord(context->hdc, - context->handle_table, - record_, - context->objects_count); + return 0 != PlayEnhMetaFileRecord(context->hdc, context->handle_table, + record_, context->objects_count); } bool Emf::Record::SafePlayback(Emf::EnumerationContext* context) const { @@ -241,7 +237,7 @@ case EMR_STRETCHDIBITS: { const EMRSTRETCHDIBITS* sdib_record = reinterpret_cast<const EMRSTRETCHDIBITS*>(record()); - const BYTE* record_start = reinterpret_cast<const BYTE *>(record()); + const BYTE* record_start = reinterpret_cast<const BYTE*>(record()); const BITMAPINFOHEADER* bmih = reinterpret_cast<const BITMAPINFOHEADER*>( record_start + sdib_record->offBmiSrc); const BYTE* bits = record_start + sdib_record->offBitsSrc; @@ -277,15 +273,13 @@ } BITMAPINFOHEADER bmi = {0}; skia::CreateBitmapHeader(bitmap->width(), bitmap->height(), &bmi); - res = (0 != StretchDIBits(hdc, sdib_record->xDest, sdib_record->yDest, - sdib_record->cxDest, - sdib_record->cyDest, sdib_record->xSrc, - sdib_record->ySrc, - sdib_record->cxSrc, sdib_record->cySrc, - pixels, - reinterpret_cast<const BITMAPINFO *>(&bmi), - sdib_record->iUsageSrc, - sdib_record->dwRop)); + res = (0 != + StretchDIBits(hdc, sdib_record->xDest, sdib_record->yDest, + sdib_record->cxDest, sdib_record->cyDest, + sdib_record->xSrc, sdib_record->ySrc, + sdib_record->cxSrc, sdib_record->cySrc, pixels, + reinterpret_cast<const BITMAPINFO*>(&bmi), + sdib_record->iUsageSrc, sdib_record->dwRop)); } } break; @@ -296,7 +290,7 @@ HDC hdc = context->hdc; if (base_matrix) { res = 0 != SetWorldTransform(hdc, base_matrix) && - ModifyWorldTransform(hdc, xform, MWT_LEFTMULTIPLY); + ModifyWorldTransform(hdc, xform, MWT_LEFTMULTIPLY); } else { res = 0 != SetWorldTransform(hdc, xform); } @@ -323,7 +317,7 @@ case 4: // MWT_SET if (base_matrix) { res = 0 != SetWorldTransform(hdc, base_matrix) && - ModifyWorldTransform(hdc, xform, MWT_LEFTMULTIPLY); + ModifyWorldTransform(hdc, xform, MWT_LEFTMULTIPLY); } else { res = 0 != SetWorldTransform(hdc, xform); } @@ -348,8 +342,7 @@ void Emf::StartPage(const gfx::Size& /*page_size*/, const gfx::Rect& /*content_area*/, - const float& /*scale_factor*/) { -} + const float& /*scale_factor*/) {} bool Emf::FinishPage() { return true; @@ -357,19 +350,15 @@ Emf::Enumerator::Enumerator(const Emf& emf, HDC context, const RECT* rect) { items_.clear(); - if (!EnumEnhMetaFile(context, - emf.emf(), - &Emf::Enumerator::EnhMetaFileProc, - reinterpret_cast<void*>(this), - rect)) { + if (!EnumEnhMetaFile(context, emf.emf(), &Emf::Enumerator::EnhMetaFileProc, + reinterpret_cast<void*>(this), rect)) { NOTREACHED(); items_.clear(); } DCHECK_EQ(context_.hdc, context); } -Emf::Enumerator::~Enumerator() { -} +Emf::Enumerator::~Enumerator() {} Emf::Enumerator::const_iterator Emf::Enumerator::begin() const { return items_.begin();
diff --git a/printing/emf_win.h b/printing/emf_win.h index 9bb4232..5245b4d 100644 --- a/printing/emf_win.h +++ b/printing/emf_win.h
@@ -24,7 +24,7 @@ namespace gfx { class Rect; class Size; -} +} // namespace gfx namespace printing {
diff --git a/printing/emf_win_unittest.cc b/printing/emf_win_unittest.cc index 9372af1..d7395f5 100644 --- a/printing/emf_win_unittest.cc +++ b/printing/emf_win_unittest.cc
@@ -94,9 +94,9 @@ base::FilePath emf_file; EXPECT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &emf_file)); emf_file = emf_file.Append(FILE_PATH_LITERAL("printing")) - .Append(FILE_PATH_LITERAL("test")) - .Append(FILE_PATH_LITERAL("data")) - .Append(FILE_PATH_LITERAL("test4.emf")); + .Append(FILE_PATH_LITERAL("test")) + .Append(FILE_PATH_LITERAL("data")) + .Append(FILE_PATH_LITERAL("test4.emf")); // Load any EMF with an image. std::string emf_data; @@ -116,15 +116,14 @@ RECT page_bounds = emf.GetPageBounds(1).ToRECT(); Emf::Enumerator emf_enum(emf, context.context(), &page_bounds); for (Emf::Enumerator::const_iterator itr = emf_enum.begin(); - itr != emf_enum.end(); - ++itr) { + itr != emf_enum.end(); ++itr) { // To help debugging. ptrdiff_t index = itr - emf_enum.begin(); // If you get this assert, you need to lookup iType in wingdi.h. It starts // with EMR_HEADER. EMR_HEADER; - EXPECT_TRUE(itr->SafePlayback(&emf_enum.context_)) << - " index: " << index << " type: " << itr->record()->iType; + EXPECT_TRUE(itr->SafePlayback(&emf_enum.context_)) + << " index: " << index << " type: " << itr->record()->iType; } context.PageDone(); context.DocumentDone();
diff --git a/printing/image.cc b/printing/image.cc index 267346d..d5667fd 100644 --- a/printing/image.cc +++ b/printing/image.cc
@@ -18,9 +18,7 @@ namespace printing { -Image::Image(const Metafile& metafile) - : row_length_(0), - ignore_alpha_(true) { +Image::Image(const Metafile& metafile) : row_length_(0), ignore_alpha_(true) { LoadMetafile(metafile); } @@ -37,19 +35,14 @@ bool Image::SaveToPng(const base::FilePath& filepath) const { DCHECK(!data_.empty()); std::vector<unsigned char> compressed; - bool success = gfx::PNGCodec::Encode(&*data_.begin(), - gfx::PNGCodec::FORMAT_BGRA, - size_, - row_length_, - true, - std::vector<gfx::PNGCodec::Comment>(), - &compressed); + bool success = gfx::PNGCodec::Encode( + &*data_.begin(), gfx::PNGCodec::FORMAT_BGRA, size_, row_length_, true, + std::vector<gfx::PNGCodec::Comment>(), &compressed); DCHECK(success && compressed.size()); if (success) { - int write_bytes = base::WriteFile( - filepath, - reinterpret_cast<char*>(&*compressed.begin()), - base::checked_cast<int>(compressed.size())); + int write_bytes = + base::WriteFile(filepath, reinterpret_cast<char*>(&*compressed.begin()), + base::checked_cast<int>(compressed.size())); success = (write_bytes == static_cast<int>(compressed.size())); DCHECK(success); } @@ -57,8 +50,8 @@ } double Image::PercentageDifferent(const Image& rhs) const { - if (size_.width() == 0 || size_.height() == 0 || - rhs.size_.width() == 0 || rhs.size_.height() == 0) + if (size_.width() == 0 || size_.height() == 0 || rhs.size_.width() == 0 || + rhs.size_.height() == 0) return 100.; int width = std::min(size_.width(), rhs.size_.width()); @@ -108,8 +101,8 @@ // Like the WebKit ImageDiff tool, we define percentage different in terms // of the size of the 'actual' bitmap. - double total_pixels = static_cast<double>(size_.width()) * - static_cast<double>(height); + double total_pixels = + static_cast<double>(size_.width()) * static_cast<double>(height); return static_cast<double>(pixels_different) / total_pixels * 100.; }
diff --git a/printing/image.h b/printing/image.h index 13ac4d5..86ef53be 100644 --- a/printing/image.h +++ b/printing/image.h
@@ -35,9 +35,7 @@ ~Image(); - const gfx::Size& size() const { - return size_; - } + const gfx::Size& size() const { return size_; } // Return a checksum of the image (MD5 over the internal data structure). std::string checksum() const;
diff --git a/printing/image_mac.cc b/printing/image_mac.cc index 1e1b683..11fc4ca 100644 --- a/printing/image_mac.cc +++ b/printing/image_mac.cc
@@ -29,14 +29,9 @@ data_.resize(bytes); base::ScopedCFTypeRef<CGColorSpaceRef> color_space( CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB)); - base::ScopedCFTypeRef<CGContextRef> bitmap_context( - CGBitmapContextCreate(&*data_.begin(), - size_.width(), - size_.height(), - 8, - row_length_, - color_space, - kCGImageAlphaPremultipliedLast)); + base::ScopedCFTypeRef<CGContextRef> bitmap_context(CGBitmapContextCreate( + &*data_.begin(), size_.width(), size_.height(), 8, row_length_, + color_space, kCGImageAlphaPremultipliedLast)); DCHECK(bitmap_context.get()); struct Metafile::MacRenderPageParams params;
diff --git a/printing/metafile.h b/printing/metafile.h index 01be9ab..a5fe9a9 100644 --- a/printing/metafile.h +++ b/printing/metafile.h
@@ -56,8 +56,7 @@ stretch_to_fit(false), center_horizontally(false), center_vertically(false), - autorotate(false) { - } + autorotate(false) {} bool shrink_to_fit; bool stretch_to_fit; @@ -113,8 +112,7 @@ // Initializes the metafile with the data in |src_buffer|. Returns true // on success. // Note: It should only be called from within the browser process. - virtual bool InitFromData(const void* src_buffer, - size_t src_buffer_size) = 0; + virtual bool InitFromData(const void* src_buffer, size_t src_buffer_size) = 0; // Prepares a context for rendering a new page with the given |page_size|, // |content_area| and a |scale_factor| to use for the drawing. The units are
diff --git a/printing/native_drawing_context.h b/printing/native_drawing_context.h index b2243f73..e1b288c 100644 --- a/printing/native_drawing_context.h +++ b/printing/native_drawing_context.h
@@ -23,6 +23,6 @@ typedef void* NativeDrawingContext; #endif -} // namespace skia +} // namespace printing #endif // PRINTING_NATIVE_DRAWING_CONTEXT_H_
diff --git a/printing/page_number.cc b/printing/page_number.cc index 19f025ff..4ec1b21 100644 --- a/printing/page_number.cc +++ b/printing/page_number.cc
@@ -21,8 +21,7 @@ : ranges_(NULL), page_number_(-1), page_range_index_(-1), - document_page_count_(0) { -} + document_page_count_(0) {} void PageNumber::operator=(const PageNumber& other) { ranges_ = other.ranges_; @@ -60,8 +59,8 @@ ++page_number_; // Page ranges are inclusive. if (page_number_ > (*ranges_)[page_range_index_].to) { - DCHECK(ranges_->size() <= static_cast<size_t>( - std::numeric_limits<int>::max())); + DCHECK(ranges_->size() <= + static_cast<size_t>(std::numeric_limits<int>::max())); if (++page_range_index_ == static_cast<int>(ranges_->size())) { // Finished. *this = npos();
diff --git a/printing/page_number.h b/printing/page_number.h index a51ad1e..9f566ae 100644 --- a/printing/page_number.h +++ b/printing/page_number.h
@@ -29,17 +29,13 @@ void Init(const PrintSettings& settings, int document_page_count); // Converts to a page numbers. - int ToInt() const { - return page_number_; - } + int ToInt() const { return page_number_; } // Calculates the next page in the serie. int operator++(); // Returns an instance that represents the end of a serie. - static const PageNumber npos() { - return PageNumber(); - } + static const PageNumber npos() { return PageNumber(); } // Equality operator. Only the current page number is verified so that // "page != PageNumber::npos()" works. @@ -62,9 +58,10 @@ }; // Debug output support. -template<class E, class T> -inline typename std::basic_ostream<E,T>& operator<<( - typename std::basic_ostream<E,T>& ss, const PageNumber& page) { +template <class E, class T> +inline typename std::basic_ostream<E, T>& operator<<( + typename std::basic_ostream<E, T>& ss, + const PageNumber& page) { return ss << page.ToInt(); }
diff --git a/printing/page_setup.cc b/printing/page_setup.cc index 3a856545..605cebf 100644 --- a/printing/page_setup.cc +++ b/printing/page_setup.cc
@@ -34,13 +34,7 @@ } // namespace PageMargins::PageMargins() - : header(0), - footer(0), - left(0), - right(0), - top(0), - bottom(0) { -} + : header(0), footer(0), left(0), right(0), top(0), bottom(0) {} void PageMargins::Clear() { header = 0; @@ -52,12 +46,8 @@ } bool PageMargins::Equals(const PageMargins& rhs) const { - return header == rhs.header && - footer == rhs.footer && - left == rhs.left && - top == rhs.top && - right == rhs.right && - bottom == rhs.bottom; + return header == rhs.header && footer == rhs.footer && left == rhs.left && + top == rhs.top && right == rhs.right && bottom == rhs.bottom; } PageSetup::PageSetup() { @@ -100,12 +90,12 @@ bool PageSetup::Equals(const PageSetup& rhs) const { return physical_size_ == rhs.physical_size_ && - printable_area_ == rhs.printable_area_ && - overlay_area_ == rhs.overlay_area_ && - content_area_ == rhs.content_area_ && - effective_margins_.Equals(rhs.effective_margins_) && - requested_margins_.Equals(rhs.requested_margins_) && - text_height_ == rhs.text_height_; + printable_area_ == rhs.printable_area_ && + overlay_area_ == rhs.overlay_area_ && + content_area_ == rhs.content_area_ && + effective_margins_.Equals(rhs.effective_margins_) && + requested_margins_.Equals(rhs.requested_margins_) && + text_height_ == rhs.text_height_; } void PageSetup::Init(const gfx::Size& physical_size, @@ -140,8 +130,7 @@ gfx::Size new_size(physical_size_.height(), physical_size_.width()); int new_y = physical_size_.width() - (printable_area_.width() + printable_area_.x()); - gfx::Rect new_printable_area(printable_area_.y(), - new_y, + gfx::Rect new_printable_area(printable_area_.y(), new_y, printable_area_.height(), printable_area_.width()); Init(new_size, new_printable_area, text_height_); @@ -162,19 +151,15 @@ void PageSetup::CalculateSizesWithinRect(const gfx::Rect& bounds, int text_height) { // Calculate the effective margins. The tricky part. - effective_margins_.header = std::max(requested_margins_.header, - bounds.y()); - effective_margins_.footer = std::max(requested_margins_.footer, - physical_size_.height() - - bounds.bottom()); - effective_margins_.left = std::max(requested_margins_.left, - bounds.x()); - effective_margins_.top = std::max(std::max(requested_margins_.top, - bounds.y()), - effective_margins_.header + text_height); + effective_margins_.header = std::max(requested_margins_.header, bounds.y()); + effective_margins_.footer = std::max( + requested_margins_.footer, physical_size_.height() - bounds.bottom()); + effective_margins_.left = std::max(requested_margins_.left, bounds.x()); + effective_margins_.top = + std::max(std::max(requested_margins_.top, bounds.y()), + effective_margins_.header + text_height); effective_margins_.right = std::max(requested_margins_.right, - physical_size_.width() - - bounds.right()); + physical_size_.width() - bounds.right()); effective_margins_.bottom = std::max(std::max(requested_margins_.bottom, physical_size_.height() - bounds.bottom()), @@ -184,27 +169,23 @@ // size will be (0, 0). overlay_area_.set_x(effective_margins_.left); overlay_area_.set_y(effective_margins_.header); - overlay_area_.set_width(std::max(0, - physical_size_.width() - - effective_margins_.right - - overlay_area_.x())); - overlay_area_.set_height(std::max(0, - physical_size_.height() - - effective_margins_.footer - - overlay_area_.y())); + overlay_area_.set_width(std::max( + 0, + physical_size_.width() - effective_margins_.right - overlay_area_.x())); + overlay_area_.set_height(std::max( + 0, + physical_size_.height() - effective_margins_.footer - overlay_area_.y())); // Calculate the content area. If the margins are excessive, the content_area // size will be (0, 0). content_area_.set_x(effective_margins_.left); content_area_.set_y(effective_margins_.top); - content_area_.set_width(std::max(0, - physical_size_.width() - - effective_margins_.right - - content_area_.x())); - content_area_.set_height(std::max(0, - physical_size_.height() - - effective_margins_.bottom - - content_area_.y())); + content_area_.set_width(std::max( + 0, + physical_size_.width() - effective_margins_.right - content_area_.x())); + content_area_.set_height(std::max( + 0, + physical_size_.height() - effective_margins_.bottom - content_area_.y())); } } // namespace printing
diff --git a/printing/page_setup.h b/printing/page_setup.h index f02ee056..4c3fa7ec 100644 --- a/printing/page_setup.h +++ b/printing/page_setup.h
@@ -48,7 +48,8 @@ // Equality operator. bool Equals(const PageSetup& rhs) const; - void Init(const gfx::Size& physical_size, const gfx::Rect& printable_area, + void Init(const gfx::Size& physical_size, + const gfx::Rect& printable_area, int text_height); // Use |requested_margins| as long as they fall inside the printable area. @@ -64,9 +65,7 @@ const gfx::Rect& overlay_area() const { return overlay_area_; } const gfx::Rect& content_area() const { return content_area_; } const gfx::Rect& printable_area() const { return printable_area_; } - const PageMargins& effective_margins() const { - return effective_margins_; - } + const PageMargins& effective_margins() const { return effective_margins_; } private: // Store |requested_margins_| and update page setup values.
diff --git a/printing/page_setup_unittest.cc b/printing/page_setup_unittest.cc index 83b1d83..bb0399d 100644 --- a/printing/page_setup_unittest.cc +++ b/printing/page_setup_unittest.cc
@@ -45,60 +45,55 @@ PageMargins effective_margins; effective_margins.header = std::max(margins.header, printable_area.y()); effective_margins.left = std::max(margins.left, printable_area.x()); - effective_margins.top = std::max(margins.top, - effective_margins.header + kTextHeight); - effective_margins.footer = std::max(margins.footer, - page_size.height() - - printable_area.bottom()); - effective_margins.right = std::max(margins.right, - page_size.width() - - printable_area.right()); - effective_margins.bottom = std::max(margins.bottom, - effective_margins.footer + kTextHeight); + effective_margins.top = + std::max(margins.top, effective_margins.header + kTextHeight); + effective_margins.footer = + std::max(margins.footer, page_size.height() - printable_area.bottom()); + effective_margins.right = + std::max(margins.right, page_size.width() - printable_area.right()); + effective_margins.bottom = + std::max(margins.bottom, effective_margins.footer + kTextHeight); // Calculate the overlay area. - gfx::Rect overlay_area(effective_margins.left, effective_margins.header, - page_size.width() - effective_margins.right - - effective_margins.left, - page_size.height() - effective_margins.footer - - effective_margins.header); + gfx::Rect overlay_area( + effective_margins.left, effective_margins.header, + page_size.width() - effective_margins.right - effective_margins.left, + page_size.height() - effective_margins.footer - effective_margins.header); // Calculate the content area. - gfx::Rect content_area(overlay_area.x(), - effective_margins.top, - overlay_area.width(), - page_size.height() - effective_margins.bottom - - effective_margins.top); + gfx::Rect content_area( + overlay_area.x(), effective_margins.top, overlay_area.width(), + page_size.height() - effective_margins.bottom - effective_margins.top); // Test values. - EXPECT_EQ(page_size, setup.physical_size()) << seed << " " << - page_size.ToString() << " " << printable_area.ToString() << - " " << kTextHeight; - EXPECT_EQ(overlay_area, setup.overlay_area()) << seed << " " << - page_size.ToString() << " " << printable_area.ToString() << - " " << kTextHeight; - EXPECT_EQ(content_area, setup.content_area()) << seed << " " << - page_size.ToString() << " " << printable_area.ToString() << - " " << kTextHeight; + EXPECT_EQ(page_size, setup.physical_size()) + << seed << " " << page_size.ToString() << " " << printable_area.ToString() + << " " << kTextHeight; + EXPECT_EQ(overlay_area, setup.overlay_area()) + << seed << " " << page_size.ToString() << " " << printable_area.ToString() + << " " << kTextHeight; + EXPECT_EQ(content_area, setup.content_area()) + << seed << " " << page_size.ToString() << " " << printable_area.ToString() + << " " << kTextHeight; - EXPECT_EQ(effective_margins.header, setup.effective_margins().header) << - seed << " " << page_size.ToString() << " " << printable_area.ToString() << - " " << kTextHeight; - EXPECT_EQ(effective_margins.footer, setup.effective_margins().footer) << - seed << " " << page_size.ToString() << " " << printable_area.ToString() << - " " << kTextHeight; - EXPECT_EQ(effective_margins.left, setup.effective_margins().left) << seed << - " " << page_size.ToString() << " " << printable_area.ToString() << - " " << kTextHeight; - EXPECT_EQ(effective_margins.top, setup.effective_margins().top) << seed << - " " << page_size.ToString() << " " << printable_area.ToString() << - " " << kTextHeight; - EXPECT_EQ(effective_margins.right, setup.effective_margins().right) << seed << - " " << page_size.ToString() << " " << printable_area.ToString() << - " " << kTextHeight; - EXPECT_EQ(effective_margins.bottom, setup.effective_margins().bottom) << - seed << " " << page_size.ToString() << " " << printable_area.ToString() << - " " << kTextHeight; + EXPECT_EQ(effective_margins.header, setup.effective_margins().header) + << seed << " " << page_size.ToString() << " " << printable_area.ToString() + << " " << kTextHeight; + EXPECT_EQ(effective_margins.footer, setup.effective_margins().footer) + << seed << " " << page_size.ToString() << " " << printable_area.ToString() + << " " << kTextHeight; + EXPECT_EQ(effective_margins.left, setup.effective_margins().left) + << seed << " " << page_size.ToString() << " " << printable_area.ToString() + << " " << kTextHeight; + EXPECT_EQ(effective_margins.top, setup.effective_margins().top) + << seed << " " << page_size.ToString() << " " << printable_area.ToString() + << " " << kTextHeight; + EXPECT_EQ(effective_margins.right, setup.effective_margins().right) + << seed << " " << page_size.ToString() << " " << printable_area.ToString() + << " " << kTextHeight; + EXPECT_EQ(effective_margins.bottom, setup.effective_margins().bottom) + << seed << " " << page_size.ToString() << " " << printable_area.ToString() + << " " << kTextHeight; } TEST(PageSetupTest, HardCoded) { @@ -137,33 +132,34 @@ gfx::Rect content_area(4, 6, 92, 88); // Test values. - EXPECT_EQ(page_size, setup.physical_size()) << " " << page_size.ToString() << - " " << printable_area.ToString() << " " << kTextHeight; - EXPECT_EQ(overlay_area, setup.overlay_area()) << " " << - page_size.ToString() << " " << printable_area.ToString() << - " " << kTextHeight; - EXPECT_EQ(content_area, setup.content_area()) << " " << - page_size.ToString() << " " << printable_area.ToString() << - " " << kTextHeight; + EXPECT_EQ(page_size, setup.physical_size()) + << " " << page_size.ToString() << " " << printable_area.ToString() << " " + << kTextHeight; + EXPECT_EQ(overlay_area, setup.overlay_area()) + << " " << page_size.ToString() << " " << printable_area.ToString() << " " + << kTextHeight; + EXPECT_EQ(content_area, setup.content_area()) + << " " << page_size.ToString() << " " << printable_area.ToString() << " " + << kTextHeight; - EXPECT_EQ(effective_margins.header, setup.effective_margins().header) << - " " << page_size.ToString() << " " << - printable_area.ToString() << " " << kTextHeight; - EXPECT_EQ(effective_margins.footer, setup.effective_margins().footer) << - " " << page_size.ToString() << " " << printable_area.ToString() << - " " << kTextHeight; - EXPECT_EQ(effective_margins.left, setup.effective_margins().left) << - " " << page_size.ToString() << " " << printable_area.ToString() << - " " << kTextHeight; - EXPECT_EQ(effective_margins.top, setup.effective_margins().top) << - " " << page_size.ToString() << " " << printable_area.ToString() << - " " << kTextHeight; - EXPECT_EQ(effective_margins.right, setup.effective_margins().right) << - " " << page_size.ToString() << " " << printable_area.ToString() << - " " << kTextHeight; - EXPECT_EQ(effective_margins.bottom, setup.effective_margins().bottom) << - " " << page_size.ToString() << " " << printable_area.ToString() << - " " << kTextHeight; + EXPECT_EQ(effective_margins.header, setup.effective_margins().header) + << " " << page_size.ToString() << " " << printable_area.ToString() << " " + << kTextHeight; + EXPECT_EQ(effective_margins.footer, setup.effective_margins().footer) + << " " << page_size.ToString() << " " << printable_area.ToString() << " " + << kTextHeight; + EXPECT_EQ(effective_margins.left, setup.effective_margins().left) + << " " << page_size.ToString() << " " << printable_area.ToString() << " " + << kTextHeight; + EXPECT_EQ(effective_margins.top, setup.effective_margins().top) + << " " << page_size.ToString() << " " << printable_area.ToString() << " " + << kTextHeight; + EXPECT_EQ(effective_margins.right, setup.effective_margins().right) + << " " << page_size.ToString() << " " << printable_area.ToString() << " " + << kTextHeight; + EXPECT_EQ(effective_margins.bottom, setup.effective_margins().bottom) + << " " << page_size.ToString() << " " << printable_area.ToString() << " " + << kTextHeight; } TEST(PageSetupTest, OutOfRangeMargins) {
diff --git a/printing/pdf_metafile_cg_mac.cc b/printing/pdf_metafile_cg_mac.cc index 265eb3a..d9d62135 100644 --- a/printing/pdf_metafile_cg_mac.cc +++ b/printing/pdf_metafile_cg_mac.cc
@@ -176,7 +176,7 @@ CGRect source_rect = CGPDFPageGetBoxRect(pdf_page, kCGPDFCropBox); int pdf_src_rotation = CGPDFPageGetRotationAngle(pdf_page); const bool source_is_landscape = - (source_rect.size.width > source_rect.size.height); + (source_rect.size.width > source_rect.size.height); const bool dest_is_landscape = (rect.size.width > rect.size.height); const bool rotate = params.autorotate ? (source_is_landscape != dest_is_landscape) : false; @@ -203,13 +203,17 @@ const float y_origin_offset = -1 * source_rect.origin.y; // If the PDF needs to be centered, calculate the offsets here. - float x_offset = params.center_horizontally ? - ((rect.size.width - (source_width * scaling_factor)) / 2) : 0; + float x_offset = + params.center_horizontally + ? ((rect.size.width - (source_width * scaling_factor)) / 2) + : 0; if (rotate) x_offset = -x_offset; - float y_offset = params.center_vertically ? - ((rect.size.height - (source_height * scaling_factor)) / 2) : 0; + float y_offset = + params.center_vertically + ? ((rect.size.height - (source_height * scaling_factor)) / 2) + : 0; CGContextSaveGState(context);
diff --git a/printing/print_job_constants.cc b/printing/print_job_constants.cc index 427a530..5817cb0 100644 --- a/printing/print_job_constants.cc +++ b/printing/print_job_constants.cc
@@ -213,7 +213,7 @@ // Whether to show PDF in view provided by OS. Implemented for MacOS only. const char kSettingOpenPDFInPreview[] = "OpenPDFInPreview"; -#if defined (USE_CUPS) +#if defined(USE_CUPS) const char kBlack[] = "Black"; const char kCMYK[] = "CMYK"; const char kKCMY[] = "KCMY";
diff --git a/printing/print_job_constants.h b/printing/print_job_constants.h index 4e601a99..017b6b8 100644 --- a/printing/print_job_constants.h +++ b/printing/print_job_constants.h
@@ -81,7 +81,7 @@ PRINTING_EXPORT extern const int COMPLETE_PREVIEW_DOCUMENT_INDEX; PRINTING_EXPORT extern const char kSettingOpenPDFInPreview[]; -#if defined (USE_CUPS) +#if defined(USE_CUPS) // Printer color models PRINTING_EXPORT extern const char kBlack[]; PRINTING_EXPORT extern const char kCMYK[]; @@ -111,17 +111,10 @@ }; // Specifies the horizontal alignment of the headers and footers. -enum HorizontalHeaderFooterPosition { - LEFT, - CENTER, - RIGHT -}; +enum HorizontalHeaderFooterPosition { LEFT, CENTER, RIGHT }; // Specifies the vertical alignment of the Headers and Footers. -enum VerticalHeaderFooterPosition { - TOP, - BOTTOM -}; +enum VerticalHeaderFooterPosition { TOP, BOTTOM }; // Print job color mode values. enum ColorModel {
diff --git a/printing/print_settings.cc b/printing/print_settings.cc index 03a6b5e..bc22112 100644 --- a/printing/print_settings.cc +++ b/printing/print_settings.cc
@@ -23,8 +23,9 @@ } #if defined(USE_CUPS) -void GetColorModelForMode( - int color_mode, std::string* color_setting_name, std::string* color_value) { +void GetColorModelForMode(int color_mode, + std::string* color_setting_name, + std::string* color_value) { #if defined(OS_MACOSX) constexpr char kCUPSColorMode[] = "ColorMode"; constexpr char kCUPSColorModel[] = "ColorModel"; @@ -246,22 +247,16 @@ case CUSTOM_MARGINS: { margins.header = 0; margins.footer = 0; - margins.top = ConvertUnitDouble( - requested_custom_margins_in_points_.top, - kPointsPerInch, - units_per_inch); - margins.bottom = ConvertUnitDouble( - requested_custom_margins_in_points_.bottom, - kPointsPerInch, - units_per_inch); - margins.left = ConvertUnitDouble( - requested_custom_margins_in_points_.left, - kPointsPerInch, - units_per_inch); - margins.right = ConvertUnitDouble( - requested_custom_margins_in_points_.right, - kPointsPerInch, - units_per_inch); + margins.top = ConvertUnitDouble(requested_custom_margins_in_points_.top, + kPointsPerInch, units_per_inch); + margins.bottom = + ConvertUnitDouble(requested_custom_margins_in_points_.bottom, + kPointsPerInch, units_per_inch); + margins.left = ConvertUnitDouble(requested_custom_margins_in_points_.left, + kPointsPerInch, units_per_inch); + margins.right = + ConvertUnitDouble(requested_custom_margins_in_points_.right, + kPointsPerInch, units_per_inch); break; } default: {
diff --git a/printing/print_settings.h b/printing/print_settings.h index 6a8c17a..7ac2275 100644 --- a/printing/print_settings.h +++ b/printing/print_settings.h
@@ -82,9 +82,7 @@ } // Media properties requested by the user. Translated into device media by the // platform specific layers. - const RequestedMedia& requested_media() const { - return requested_media_; - } + const RequestedMedia& requested_media() const { return requested_media_; } // Set printer printable area in in device units. // Some platforms already provide flipped area. Set |landscape_needs_flip| @@ -126,7 +124,7 @@ int device_units_per_inch() const { #if defined(OS_MACOSX) return 72; -#else // defined(OS_MACOSX) +#else // defined(OS_MACOSX) return dpi(); #endif // defined(OS_MACOSX) } @@ -175,7 +173,7 @@ bool printer_is_textonly() const { return printer_type_ == PrinterType::TYPE_TEXTONLY; } - bool printer_is_xps() const { return printer_type_ == PrinterType::TYPE_XPS;} + bool printer_is_xps() const { return printer_type_ == PrinterType::TYPE_XPS; } bool printer_is_ps2() const { return printer_type_ == PrinterType::TYPE_POSTSCRIPT_LEVEL2; }
diff --git a/printing/print_settings_conversion.h b/printing/print_settings_conversion.h index 07b6b03..678440da 100644 --- a/printing/print_settings_conversion.h +++ b/printing/print_settings_conversion.h
@@ -12,7 +12,7 @@ namespace base { class DictionaryValue; class Value; -} +} // namespace base namespace printing {
diff --git a/printing/print_settings_initializer_mac.cc b/printing/print_settings_initializer_mac.cc index dcb9c97..065645a 100644 --- a/printing/print_settings_initializer_mac.cc +++ b/printing/print_settings_initializer_mac.cc
@@ -25,9 +25,9 @@ print_settings->SetOrientation(orientation == kPMLandscape); UInt32 resolution_count = 0; - PMResolution best_resolution = { 72.0, 72.0 }; - OSStatus status = PMPrinterGetPrinterResolutionCount(printer, - &resolution_count); + PMResolution best_resolution = {72.0, 72.0}; + OSStatus status = + PMPrinterGetPrinterResolutionCount(printer, &resolution_count); if (status == noErr) { // Resolution indexes are 1-based. for (uint32_t i = 1; i <= resolution_count; ++i) { @@ -48,19 +48,15 @@ PMGetAdjustedPaperRect(page_format, &paper_rect); // Device units are in points. Units per inch is 72. - gfx::Size physical_size_device_units( - (paper_rect.right - paper_rect.left), - (paper_rect.bottom - paper_rect.top)); + gfx::Size physical_size_device_units((paper_rect.right - paper_rect.left), + (paper_rect.bottom - paper_rect.top)); gfx::Rect printable_area_device_units( - (page_rect.left - paper_rect.left), - (page_rect.top - paper_rect.top), - (page_rect.right - page_rect.left), - (page_rect.bottom - page_rect.top)); + (page_rect.left - paper_rect.left), (page_rect.top - paper_rect.top), + (page_rect.right - page_rect.left), (page_rect.bottom - page_rect.top)); DCHECK_EQ(print_settings->device_units_per_inch(), kPointsPerInch); print_settings->SetPrinterPrintableArea(physical_size_device_units, - printable_area_device_units, - false); + printable_area_device_units, false); } } // namespace printing
diff --git a/printing/print_settings_initializer_win.cc b/printing/print_settings_initializer_win.cc index 88b4eb0..f844882 100644 --- a/printing/print_settings_initializer_win.cc +++ b/printing/print_settings_initializer_win.cc
@@ -112,7 +112,7 @@ print_settings->set_dpi_xy(dpi_x, dpi_y); const int kAlphaCaps = SB_CONST_ALPHA | SB_PIXEL_ALPHA; print_settings->set_supports_alpha_blend( - (GetDeviceCaps(hdc, SHADEBLENDCAPS) & kAlphaCaps) == kAlphaCaps); + (GetDeviceCaps(hdc, SHADEBLENDCAPS) & kAlphaCaps) == kAlphaCaps); DCHECK_EQ(GetDeviceCaps(hdc, SCALINGFACTORX), 0); DCHECK_EQ(GetDeviceCaps(hdc, SCALINGFACTORY), 0); @@ -134,14 +134,13 @@ // Sanity check the printable_area: we've seen crashes caused by a printable // area rect of 0, 0, 0, 0, so it seems some drivers don't set it. if (printable_area_device_units.IsEmpty() || - !gfx::Rect(physical_size_device_units).Contains( - printable_area_device_units)) { + !gfx::Rect(physical_size_device_units) + .Contains(printable_area_device_units)) { printable_area_device_units = gfx::Rect(physical_size_device_units); } DCHECK_EQ(print_settings->device_units_per_inch(), dpi); print_settings->SetPrinterPrintableArea(physical_size_device_units, - printable_area_device_units, - false); + printable_area_device_units, false); print_settings->set_color(IsDevModeWithColor(&dev_mode) ? COLOR : GRAY);
diff --git a/printing/printed_document.cc b/printing/printed_document.cc index f1f61fd..2f695880a 100644 --- a/printing/printed_document.cc +++ b/printing/printed_document.cc
@@ -81,8 +81,7 @@ PrintedDocument::CreateDebugDumpPath(doc_name, extension); if (path.empty()) return; - base::WriteFile(path, - reinterpret_cast<const char*>(data->front()), + base::WriteFile(path, reinterpret_cast<const char*>(data->front()), base::checked_cast<int>(data->size())); }
diff --git a/printing/printed_document_win.cc b/printing/printed_document_win.cc index 19bfb45..e083520 100644 --- a/printing/printed_document_win.cc +++ b/printing/printed_document_win.cc
@@ -16,7 +16,7 @@ int offset_x, int offset_y, float shrink_factor) { - XFORM xform = { 0 }; + XFORM xform = {0}; xform.eDx = static_cast<float>(offset_x); xform.eDy = static_cast<float>(offset_y); xform.eM11 = xform.eM22 = 1.f / shrink_factor; @@ -60,8 +60,7 @@ // Note that the printing output is relative to printable area of the page. // That is 0,0 is offset by PHYSICALOFFSETX/Y from the page. SimpleModifyWorldTransform( - context, - content_area.x() - page_setup.printable_area().x(), + context, content_area.x() - page_setup.printable_area().x(), content_area.y() - page_setup.printable_area().y(), page.shrink_factor());
diff --git a/printing/printing_context.cc b/printing/printing_context.cc index 6423238a..78e3c3b2 100644 --- a/printing/printing_context.cc +++ b/printing/printing_context.cc
@@ -18,9 +18,7 @@ } PrintingContext::PrintingContext(Delegate* delegate) - : delegate_(delegate), - in_print_job_(false), - abort_printing_(false) { + : delegate_(delegate), in_print_job_(false), abort_printing_(false) { DCHECK(delegate_); }
diff --git a/printing/printing_context.h b/printing/printing_context.h index a5879b58..9ccc1a66 100644 --- a/printing/printing_context.h +++ b/printing/printing_context.h
@@ -125,9 +125,7 @@ void set_margin_type(MarginType type); void set_is_modifiable(bool is_modifiable); - const PrintSettings& settings() const { - return settings_; - } + const PrintSettings& settings() const { return settings_; } int job_id() const { return job_id_; }
diff --git a/printing/printing_context_android.cc b/printing/printing_context_android.cc index a381582..ec40ab6 100644 --- a/printing/printing_context_android.cc +++ b/printing/printing_context_android.cc
@@ -40,8 +40,7 @@ settings->set_dpi(dpi); settings->SetPrinterPrintableArea(physical_size_device_units, - printable_area_device_units, - false); + printable_area_device_units, false); } void GetPageRanges(JNIEnv* env, @@ -86,8 +85,7 @@ // The constructor is run in the IO thread. } -PrintingContextAndroid::~PrintingContextAndroid() { -} +PrintingContextAndroid::~PrintingContextAndroid() {} void PrintingContextAndroid::AskUserForSettings( int max_pages, @@ -99,9 +97,8 @@ JNIEnv* env = base::android::AttachCurrentThread(); if (j_printing_context_.is_null()) { - j_printing_context_.Reset(Java_PrintingContext_create( - env, - reinterpret_cast<intptr_t>(this))); + j_printing_context_.Reset( + Java_PrintingContext_create(env, reinterpret_cast<intptr_t>(this))); } if (is_scripted) { @@ -181,16 +178,16 @@ int32_t width = 0; int32_t height = 0; UErrorCode error = U_ZERO_ERROR; - ulocdata_getPaperSize( - delegate_->GetAppLocale().c_str(), &height, &width, &error); + ulocdata_getPaperSize(delegate_->GetAppLocale().c_str(), &height, &width, + &error); if (error > U_ZERO_ERROR) { // If the call failed, assume a paper size of 8.5 x 11 inches. LOG(WARNING) << "ulocdata_getPaperSize failed, using 8.5 x 11, error: " << error; - width = static_cast<int>( - kLetterWidthInch * settings_.device_units_per_inch()); - height = static_cast<int>( - kLetterHeightInch * settings_.device_units_per_inch()); + width = + static_cast<int>(kLetterWidthInch * settings_.device_units_per_inch()); + height = + static_cast<int>(kLetterHeightInch * settings_.device_units_per_inch()); } else { // ulocdata_getPaperSize returns the width and height in mm. // Convert this to pixels based on the dpi.
diff --git a/printing/printing_context_linux.h b/printing/printing_context_linux.h index 1dd5085..2ceb3be 100644 --- a/printing/printing_context_linux.h +++ b/printing/printing_context_linux.h
@@ -22,9 +22,8 @@ ~PrintingContextLinux() override; // Sets the function that creates the print dialog. - static void SetCreatePrintDialogFunction( - PrintDialogGtkInterface* (*create_dialog_func)( - PrintingContextLinux* context)); + static void SetCreatePrintDialogFunction(PrintDialogGtkInterface* ( + *create_dialog_func)(PrintingContextLinux* context)); // Sets the function that returns pdf paper size through the native API. static void SetPdfPaperSizeFunction(
diff --git a/printing/printing_context_mac.mm b/printing/printing_context_mac.mm index bd1a197..dc1694d 100644 --- a/printing/printing_context_mac.mm +++ b/printing/printing_context_mac.mm
@@ -42,7 +42,7 @@ PMPaper best_matching_paper = NULL; int num_papers = CFArrayGetCount(paper_list); for (int i = 0; i < num_papers; ++i) { - PMPaper paper = (PMPaper)[(NSArray*)paper_list objectAtIndex : i]; + PMPaper paper = (PMPaper)[(NSArray*)paper_list objectAtIndex:i]; double paper_width = 0.0; double paper_height = 0.0; PMPaperGetWidth(paper, &paper_width); @@ -75,8 +75,7 @@ PrintingContextMac::PrintingContextMac(Delegate* delegate) : PrintingContext(delegate), print_info_([[NSPrintInfo sharedPrintInfo] copy]), - context_(NULL) { -} + context_(NULL) {} PrintingContextMac::~PrintingContextMac() { ReleaseContext(); @@ -153,9 +152,8 @@ PMGetAdjustedPaperRect(page_format, &paper_rect); // Device units are in points. Units per inch is 72. - gfx::Size physical_size_device_units( - (paper_rect.right - paper_rect.left), - (paper_rect.bottom - paper_rect.top)); + gfx::Size physical_size_device_units((paper_rect.right - paper_rect.left), + (paper_rect.bottom - paper_rect.top)); DCHECK(settings_.device_units_per_inch() == kPointsPerInch); return physical_size_device_units; } @@ -211,9 +209,8 @@ static_cast<PMPrintSession>([print_info_.get() PMPrintSession]); PMPrintSettings print_settings = static_cast<PMPrintSettings>([print_info_.get() PMPrintSettings]); - return PMSessionSetDestination( - print_session, print_settings, kPMDestinationPreview, - NULL, NULL) == noErr; + return PMSessionSetDestination(print_session, print_settings, + kPMDestinationPreview, NULL, NULL) == noErr; } void PrintingContextMac::InitPrintSettingsFromPrintInfo() { @@ -223,8 +220,8 @@ static_cast<PMPageFormat>([print_info_.get() PMPageFormat]); PMPrinter printer; PMSessionGetCurrentPrinter(print_session, &printer); - PrintSettingsInitializerMac::InitPrintSettings( - printer, page_format, &settings_); + PrintSettingsInitializerMac::InitPrintSettings(printer, page_format, + &settings_); } bool PrintingContextMac::SetPrinter(const std::string& device_name) { @@ -246,7 +243,7 @@ return false; if (CFStringCompare(new_printer_id.get(), current_printer_id, 0) == - kCFCompareEqualTo) { + kCFCompareEqualTo) { return true; } @@ -312,13 +309,9 @@ return true; PMPaper paper = NULL; - if (PMPaperCreateCustom(current_printer, - CFSTR("Custom paper ID"), - CFSTR("Custom paper"), - page_width, - page_height, - &margins, - &paper) != noErr) { + if (PMPaperCreateCustom(current_printer, CFSTR("Custom paper ID"), + CFSTR("Custom paper"), page_width, page_height, + &margins, &paper) != noErr) { return false; } bool result = UpdatePageFormatWithPaper(paper, default_page_format); @@ -403,10 +396,8 @@ base::ScopedCFTypeRef<CFStringRef> output_color( base::SysUTF8ToCFStringRef(color_value)); - return PMPrintSettingsSetValue(pmPrintSettings, - color_setting.get(), - output_color.get(), - false) == noErr; + return PMPrintSettingsSetValue(pmPrintSettings, color_setting.get(), + output_color.get(), false) == noErr; } PageRanges PrintingContextMac::GetPageRangesFromPrintInfo() { @@ -438,9 +429,8 @@ base::SysUTF16ToCFStringRef(document_name)); PMPrintSettingsSetJobName(print_settings, job_title.get()); - OSStatus status = PMSessionBeginCGDocumentNoDialog(print_session, - print_settings, - page_format); + OSStatus status = PMSessionBeginCGDocumentNoDialog( + print_session, print_settings, page_format); if (status != noErr) return OnError();
diff --git a/printing/printing_context_no_system_dialog.cc b/printing/printing_context_no_system_dialog.cc index 6679fd70..65d9bd2 100644 --- a/printing/printing_context_no_system_dialog.cc +++ b/printing/printing_context_no_system_dialog.cc
@@ -25,8 +25,7 @@ #endif // !defined(USE_CUPS) PrintingContextNoSystemDialog::PrintingContextNoSystemDialog(Delegate* delegate) - : PrintingContext(delegate) { -} + : PrintingContext(delegate) {} PrintingContextNoSystemDialog::~PrintingContextNoSystemDialog() { ReleaseContext(); @@ -58,16 +57,16 @@ int32_t width = 0; int32_t height = 0; UErrorCode error = U_ZERO_ERROR; - ulocdata_getPaperSize( - delegate_->GetAppLocale().c_str(), &height, &width, &error); + ulocdata_getPaperSize(delegate_->GetAppLocale().c_str(), &height, &width, + &error); if (error > U_ZERO_ERROR) { // If the call failed, assume a paper size of 8.5 x 11 inches. LOG(WARNING) << "ulocdata_getPaperSize failed, using 8.5 x 11, error: " << error; - width = static_cast<int>( - kLetterWidthInch * settings_.device_units_per_inch()); - height = static_cast<int>( - kLetterHeightInch * settings_.device_units_per_inch()); + width = + static_cast<int>(kLetterWidthInch * settings_.device_units_per_inch()); + height = + static_cast<int>(kLetterHeightInch * settings_.device_units_per_inch()); } else { // ulocdata_getPaperSize returns the width and height in mm. // Convert this to pixels based on the dpi. @@ -142,4 +141,3 @@ } } // namespace printing -
diff --git a/printing/printing_context_system_dialog_win.cc b/printing/printing_context_system_dialog_win.cc index f146351..1c2d08a7 100644 --- a/printing/printing_context_system_dialog_win.cc +++ b/printing/printing_context_system_dialog_win.cc
@@ -135,8 +135,8 @@ settings_.set_ranges(ranges_vector); settings_.set_device_name(new_device_name); settings_.set_selection_only(selection_only); - PrintSettingsInitializerWin::InitPrintSettings( - context(), dev_mode, &settings_); + PrintSettingsInitializerWin::InitPrintSettings(context(), dev_mode, + &settings_); return true; }
diff --git a/printing/printing_context_system_dialog_win.h b/printing/printing_context_system_dialog_win.h index f402e1b..7781cfd55 100644 --- a/printing/printing_context_system_dialog_win.h +++ b/printing/printing_context_system_dialog_win.h
@@ -5,8 +5,9 @@ #ifndef PRINTING_PRINTING_CONTEXT_SYSTEM_DIALOG_WIN_H_ #define PRINTING_PRINTING_CONTEXT_SYSTEM_DIALOG_WIN_H_ -#include <ocidl.h> -#include <commdlg.h> +#include <ocidl.h> // NOLINT(build/include_order) + +#include <commdlg.h> // Must come after ocidl.h. #include <string>
diff --git a/printing/printing_context_win.cc b/printing/printing_context_win.cc index d0b9503..eee0f77 100644 --- a/printing/printing_context_win.cc +++ b/printing/printing_context_win.cc
@@ -137,9 +137,8 @@ break; } } - return gfx::Size( - paper_size.width() * settings_.device_units_per_inch(), - paper_size.height() * settings_.device_units_per_inch()); + return gfx::Size(paper_size.width() * settings_.device_units_per_inch(), + paper_size.height() * settings_.device_units_per_inch()); } PrintingContext::Result PrintingContextWin::UpdatePrinterSettings( @@ -166,8 +165,8 @@ dev_mode->dmCopies = std::max(settings_.copies(), 1); if (dev_mode->dmCopies > 1) { // do not change unless multiple copies dev_mode->dmFields |= DM_COPIES; - dev_mode->dmCollate = settings_.collate() ? DMCOLLATE_TRUE : - DMCOLLATE_FALSE; + dev_mode->dmCollate = + settings_.collate() ? DMCOLLATE_TRUE : DMCOLLATE_FALSE; } switch (settings_.duplex_mode()) { @@ -188,8 +187,8 @@ } dev_mode->dmFields |= DM_ORIENTATION; - dev_mode->dmOrientation = settings_.landscape() ? DMORIENT_LANDSCAPE : - DMORIENT_PORTRAIT; + dev_mode->dmOrientation = + settings_.landscape() ? DMORIENT_LANDSCAPE : DMORIENT_PORTRAIT; if (settings_.dpi_horizontal() > 0) { dev_mode->dmPrintQuality = settings_.dpi_horizontal(); @@ -261,7 +260,7 @@ return OnError(); DCHECK(SimplifyDocumentTitle(document_name) == document_name); - DOCINFO di = { sizeof(DOCINFO) }; + DOCINFO di = {sizeof(DOCINFO)}; di.lpszDocName = document_name.c_str(); // Is there a debug dump directory specified? If so, force to print to a file. @@ -365,8 +364,8 @@ DCHECK(!in_print_job_); settings_.set_device_name(device_name); - PrintSettingsInitializerWin::InitPrintSettings( - context_, *dev_mode, &settings_); + PrintSettingsInitializerWin::InitPrintSettings(context_, *dev_mode, + &settings_); return OK; }
diff --git a/printing/printing_context_win_unittest.cc b/printing/printing_context_win_unittest.cc index 00e9ada..1868b9ea 100644 --- a/printing/printing_context_win_unittest.cc +++ b/printing/printing_context_win_unittest.cc
@@ -183,7 +183,7 @@ // The print may lie to use and may not support world transformation. // Verify right now. - XFORM random_matrix = { 1, 0.1f, 0, 1.5f, 0, 1 }; + XFORM random_matrix = {1, 0.1f, 0, 1.5f, 0, 1}; EXPECT_TRUE(SetWorldTransform(context.context(), &random_matrix)); EXPECT_TRUE(ModifyWorldTransform(context.context(), nullptr, MWT_IDENTITY)); }
diff --git a/printing/printing_test.h b/printing/printing_test.h index df391958..0839204 100644 --- a/printing/printing_test.h +++ b/printing/printing_test.h
@@ -15,12 +15,10 @@ // Disable the whole test case when executing on a computer that has no printer // installed. // Note: Parent should be testing::Test or InProcessBrowserTest. -template<typename Parent> +template <typename Parent> class PrintingTest : public Parent { public: - static bool IsTestCaseDisabled() { - return GetDefaultPrinter().empty(); - } + static bool IsTestCaseDisabled() { return GetDefaultPrinter().empty(); } static std::wstring GetDefaultPrinter() { wchar_t printer_name[MAX_PATH]; DWORD size = base::size(printer_name);
diff --git a/printing/units.h b/printing/units.h index 88aea52..7b83577a 100644 --- a/printing/units.h +++ b/printing/units.h
@@ -47,7 +47,8 @@ PRINTING_EXPORT int ConvertUnit(double value, int old_unit, int new_unit); // Converts from one unit system to another using doubles. -PRINTING_EXPORT double ConvertUnitDouble(double value, double old_unit, +PRINTING_EXPORT double ConvertUnitDouble(double value, + double old_unit, double new_unit); // Converts from 1 pixel to 1 point using integers.
diff --git a/printing/units_unittest.cc b/printing/units_unittest.cc index f651895..f43dabd 100644 --- a/printing/units_unittest.cc +++ b/printing/units_unittest.cc
@@ -3,8 +3,8 @@ // found in the LICENSE file. #include "printing/units.h" -#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest-spi.h" +#include "testing/gtest/include/gtest/gtest.h" namespace printing {
diff --git a/remoting/base/BUILD.gn b/remoting/base/BUILD.gn index d6d3ba7..f3d95104 100644 --- a/remoting/base/BUILD.gn +++ b/remoting/base/BUILD.gn
@@ -111,6 +111,10 @@ "//google_apis", "//net", ] + + deps = [ + "//remoting/proto/remoting/v1:directory_grpc_library", + ] } source_set("breakpad") {
diff --git a/remoting/base/oauth_token_exchanger.cc b/remoting/base/oauth_token_exchanger.cc index 10f6575..d4c0429 100644 --- a/remoting/base/oauth_token_exchanger.cc +++ b/remoting/base/oauth_token_exchanger.cc
@@ -11,7 +11,14 @@ #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "google_apis/gaia/gaia_oauth_client.h" +#include "google_apis/google_api_keys.h" +#include "remoting/base/grpc_support/grpc_async_executor.h" +#include "remoting/base/grpc_support/grpc_async_unary_request.h" +#include "remoting/base/grpc_support/grpc_channel.h" +#include "remoting/base/service_urls.h" +#include "remoting/proto/remoting/v1/directory_service.grpc.pb.h" #include "services/network/public/cpp/shared_url_loader_factory.h" +#include "third_party/grpc/src/include/grpcpp/security/credentials.h" namespace remoting { @@ -38,10 +45,56 @@ } // namespace +class OAuthTokenExchanger::DirectoryServiceClient { + public: + using UpdateRobotTokenCallback = + base::OnceCallback<void(const grpc::Status&, + const apis::v1::UpdateRobotTokenResponse&)>; + + DirectoryServiceClient(); + ~DirectoryServiceClient(); + + void UpdateRobotToken(const std::string& access_token, + UpdateRobotTokenCallback callback); + + private: + using RemotingDirectoryService = apis::v1::RemotingDirectoryService; + + GrpcAsyncExecutor grpc_executor_; + std::unique_ptr<RemotingDirectoryService::Stub> stub_; +}; + +OAuthTokenExchanger::DirectoryServiceClient::DirectoryServiceClient() { + GrpcChannelSharedPtr channel = CreateSslChannelForEndpoint( + ServiceUrls::GetInstance()->remoting_server_endpoint()); + stub_ = RemotingDirectoryService::NewStub(channel); +} + +OAuthTokenExchanger::DirectoryServiceClient::~DirectoryServiceClient() = + default; + +void OAuthTokenExchanger::DirectoryServiceClient::UpdateRobotToken( + const std::string& access_token, + UpdateRobotTokenCallback callback) { + auto update_robot_token_request = apis::v1::UpdateRobotTokenRequest(); + update_robot_token_request.set_client_id( + google_apis::GetOAuth2ClientID(google_apis::CLIENT_REMOTING_HOST)); + update_robot_token_request.set_offline(false); + + auto async_request = CreateGrpcAsyncUnaryRequest( + base::BindOnce(&RemotingDirectoryService::Stub::AsyncUpdateRobotToken, + base::Unretained(stub_.get())), + update_robot_token_request, std::move(callback)); + async_request->context()->set_credentials( + grpc::AccessTokenCredentials(access_token)); + grpc_executor_.ExecuteRpc(std::move(async_request)); +} + OAuthTokenExchanger::OAuthTokenExchanger( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) : gaia_oauth_client_(std::make_unique<gaia::GaiaOAuthClient>( - std::move(url_loader_factory))) {} + std::move(url_loader_factory))), + directory_service_client_(std::make_unique<DirectoryServiceClient>()) {} OAuthTokenExchanger::~OAuthTokenExchanger() = default; @@ -64,6 +117,14 @@ NotifyCallbacks(OAuthTokenGetter::SUCCESS, oauth_access_token_); } +void OAuthTokenExchanger::OnGetTokensResponse(const std::string& refresh_token, + const std::string& access_token, + int expires_in_seconds) { + // |expires_in_seconds| is unused - the exchanged token is assumed to be + // valid for at least as long as the original access token. + NotifyCallbacks(OAuthTokenGetter::SUCCESS, access_token); +} + void OAuthTokenExchanger::OnGetTokenInfoResponse( std::unique_ptr<base::DictionaryValue> token_info) { base::Value* scopes_value = token_info->FindKey(TOKENINFO_SCOPE_KEY); @@ -105,8 +166,37 @@ } void OAuthTokenExchanger::RequestNewToken() { - NOTIMPLEMENTED() << "Token exchange not yet implemented."; - NotifyCallbacks(OAuthTokenGetter::SUCCESS, oauth_access_token_); + directory_service_client_->UpdateRobotToken( + oauth_access_token_, + base::BindOnce(&OAuthTokenExchanger::OnRobotTokenResponse, + base::Unretained(this))); +} + +void OAuthTokenExchanger::OnRobotTokenResponse( + const grpc::Status& status, + const apis::v1::UpdateRobotTokenResponse& response) { + if (!status.ok()) { + LOG(ERROR) << "Received error code: " << status.error_code() + << ", message: " << status.error_message(); + NotifyCallbacks(OAuthTokenGetter::AUTH_ERROR, std::string()); + return; + } + + if (!response.has_auth_code()) { + LOG(ERROR) << "Received response without auth_code."; + NotifyCallbacks(OAuthTokenGetter::AUTH_ERROR, std::string()); + return; + } + + // The redirect_uri parameter is required for GetTokensFromAuthCode(), but + // "oob" (out of band) can be used for robot accounts. + gaia::OAuthClientInfo client_info = { + google_apis::GetOAuth2ClientID(google_apis::CLIENT_REMOTING_HOST), + google_apis::GetOAuth2ClientSecret(google_apis::CLIENT_REMOTING_HOST), + "oob"}; + + gaia_oauth_client_->GetTokensFromAuthCode(client_info, response.auth_code(), + kMaxRetries, this); } } // namespace remoting
diff --git a/remoting/base/oauth_token_exchanger.h b/remoting/base/oauth_token_exchanger.h index 194c360..18cf54d17 100644 --- a/remoting/base/oauth_token_exchanger.h +++ b/remoting/base/oauth_token_exchanger.h
@@ -16,8 +16,18 @@ #include "google_apis/gaia/gaia_oauth_client.h" #include "remoting/base/oauth_token_getter.h" +namespace grpc { +class Status; +} // namespace grpc + namespace remoting { +namespace apis { +namespace v1 { +class UpdateRobotTokenResponse; +} // namespace v1 +} // namespace apis + class OAuthTokenExchanger : public gaia::GaiaOAuthClient::Delegate { public: typedef base::OnceCallback<void(OAuthTokenGetter::Status status, @@ -32,15 +42,22 @@ TokenCallback on_new_token); // gaia::GaiaOAuthClient::Delegate interface. + void OnGetTokensResponse(const std::string& refresh_token, + const std::string& access_token, + int expires_in_seconds) override; void OnGetTokenInfoResponse( std::unique_ptr<base::DictionaryValue> token_info) override; void OnOAuthError() override; void OnNetworkError(int response_code) override; private: + class DirectoryServiceClient; + void NotifyCallbacks(OAuthTokenGetter::Status status, const std::string& access_token); void RequestNewToken(); + void OnRobotTokenResponse(const grpc::Status& status, + const apis::v1::UpdateRobotTokenResponse& response); std::unique_ptr<gaia::GaiaOAuthClient> gaia_oauth_client_; base::queue<TokenCallback> pending_callbacks_; @@ -52,6 +69,9 @@ // Unset if the scopes are unknown and the tokeninfo endpoint needs to be // queried. base::Optional<bool> need_token_exchange_; + + std::unique_ptr<DirectoryServiceClient> directory_service_client_; + DISALLOW_COPY_AND_ASSIGN(OAuthTokenExchanger); };
diff --git a/remoting/proto/remoting/v1/directory_messages.proto b/remoting/proto/remoting/v1/directory_messages.proto index 560c76f6..68404a0 100644 --- a/remoting/proto/remoting/v1/directory_messages.proto +++ b/remoting/proto/remoting/v1/directory_messages.proto
@@ -98,7 +98,12 @@ // Requests an auth_code with updated OAuth scopes. Should only be called by // robot accounts assigned to a Me2me host. -message UpdateRobotTokenRequest {} +message UpdateRobotTokenRequest { + // OAuth client ID of the requesting host. + optional string client_id = 1; + // Whether to request offline access. + optional bool offline = 2; +} // Response to a UpdateRobotTokenRequest. message UpdateRobotTokenResponse {
diff --git a/services/BUILD.gn b/services/BUILD.gn index 0f33ba75..773980e 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn
@@ -48,7 +48,6 @@ deps += [ "//services/ws/input_devices:tests", "//services/ws/public/cpp/tests", - "//services/ws/public/mojom:tests", ] }
diff --git a/services/media_session/audio_focus_manager.cc b/services/media_session/audio_focus_manager.cc index 5b334c2f..413782c 100644 --- a/services/media_session/audio_focus_manager.cc +++ b/services/media_session/audio_focus_manager.cc
@@ -299,24 +299,9 @@ if (audio_focus_stack_.empty()) return; - if (audio_focus_stack_.back()->id() != id) { - RemoveFocusEntryIfPresent(id); - MaybeUpdateActiveSession(); - return; - } + bool was_top_most_session = audio_focus_stack_.back()->id() == id; - auto row = std::move(audio_focus_stack_.back()); - audio_focus_stack_.pop_back(); - - if (audio_focus_stack_.empty()) { - // Notify observers that we lost audio focus. - observers_.ForAllPtrs([&row](mojom::AudioFocusObserver* observer) { - observer->OnFocusLost(row->ToAudioFocusRequestState()); - }); - - MaybeUpdateActiveSession(); - return; - } + auto row = RemoveFocusEntryIfPresent(id); EnforceAudioFocus(); MaybeUpdateActiveSession(); @@ -326,6 +311,9 @@ observer->OnFocusLost(row->ToAudioFocusRequestState()); }); + if (!was_top_most_session || audio_focus_stack_.empty()) + return; + // Notify observers that the session on top gained focus. StackRow* new_session = audio_focus_stack_.back().get(); observers_.ForAllPtrs([&new_session](mojom::AudioFocusObserver* observer) {
diff --git a/services/media_session/audio_focus_manager_unittest.cc b/services/media_session/audio_focus_manager_unittest.cc index 1231095..518b937 100644 --- a/services/media_session/audio_focus_manager_unittest.cc +++ b/services/media_session/audio_focus_manager_unittest.cc
@@ -1457,4 +1457,30 @@ GetState(&media_session_1)); } +TEST_P(AudioFocusManagerTest, AudioFocusObserver_NotTopMost) { + test::MockMediaSession media_session_1; + test::MockMediaSession media_session_2; + + AudioFocusManager::RequestId request_id_1 = + RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain); + EXPECT_EQ(request_id_1, GetAudioFocusedSession()); + EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive, + GetState(&media_session_1)); + + RequestAudioFocus(&media_session_2, + mojom::AudioFocusType::kGainTransientMayDuck); + EXPECT_EQ(GetStateFromParam(mojom::MediaSessionInfo::SessionState::kDucking), + GetState(&media_session_1)); + EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive, + GetState(&media_session_2)); + + { + std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver(); + media_session_1.AbandonAudioFocusFromClient(); + + EXPECT_TRUE(observer->focus_lost_session()->session_info.Equals( + test::GetMediaSessionInfoSync(&media_session_1))); + } +} + } // namespace media_session
diff --git a/services/network/throttling/throttling_controller.cc b/services/network/throttling/throttling_controller.cc index 06176d94..79a3829 100644 --- a/services/network/throttling/throttling_controller.cc +++ b/services/network/throttling/throttling_controller.cc
@@ -14,7 +14,9 @@ ThrottlingController* ThrottlingController::instance_ = nullptr; ThrottlingController::ThrottlingController() = default; -ThrottlingController::~ThrottlingController() = default; +ThrottlingController::~ThrottlingController() { + liveness_ = Liveness::kDead; +} // static void ThrottlingController::SetConditions( @@ -57,6 +59,7 @@ // Null |instance_| means there is no network condition registered. if (!instance_) return false; + instance_->CheckValidThread(); return instance_->interceptors_.find(throttling_profile_id) != instance_->interceptors_.end(); } @@ -64,20 +67,20 @@ void ThrottlingController::Register( uint32_t net_log_source_id, const base::UnguessableToken& throttling_profile_id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + CheckValidThread(); if (interceptors_.find(throttling_profile_id) == interceptors_.end()) return; net_log_source_profile_map_[net_log_source_id] = throttling_profile_id; } void ThrottlingController::Unregister(uint32_t net_log_source_id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + CheckValidThread(); net_log_source_profile_map_.erase(net_log_source_id); } base::Optional<base::UnguessableToken> ThrottlingController::GetProfileID( uint32_t net_log_source_id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + CheckValidThread(); auto it = net_log_source_profile_map_.find(net_log_source_id); if (it == net_log_source_profile_map_.end()) return base::nullopt; @@ -87,7 +90,7 @@ void ThrottlingController::SetNetworkConditions( const base::UnguessableToken& throttling_profile_id, std::unique_ptr<NetworkConditions> conditions) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + CheckValidThread(); auto it = interceptors_.find(throttling_profile_id); if (it == interceptors_.end()) { @@ -113,9 +116,28 @@ } } +static NOINLINE void CrashBecauseThrottlingControllerDeleted() { + LOG(ERROR) << "deleted"; + CHECK(false); +} + +static NOINLINE void CrashBecauseThrottlingControllerBad() { + LOG(ERROR) << "bad"; + CHECK(false); +} + ThrottlingNetworkInterceptor* ThrottlingController::FindInterceptor( uint32_t net_log_source_id) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + CheckValidThread(); + + if (liveness_ == Liveness::kDead) { + CrashBecauseThrottlingControllerDeleted(); + } else if (liveness_ != Liveness::kAlive) { + Liveness liveness = liveness_; + base::debug::Alias(&liveness); + CrashBecauseThrottlingControllerBad(); + } + auto source_profile_map_it = net_log_source_profile_map_.find(net_log_source_id); if (source_profile_map_it == net_log_source_profile_map_.end()) @@ -124,4 +146,8 @@ return it != interceptors_.end() ? it->second.get() : nullptr; } +void ThrottlingController::CheckValidThread() { + CHECK(thread_checker_.CalledOnValidThread()); +} + } // namespace network
diff --git a/services/network/throttling/throttling_controller.h b/services/network/throttling/throttling_controller.h index f304242..43751c4 100644 --- a/services/network/throttling/throttling_controller.h +++ b/services/network/throttling/throttling_controller.h
@@ -36,6 +36,13 @@ private: friend class ScopedThrottlingToken; + // TODO(https://crbug.com/960874): Debugging code to try and shed some light + // on why the owned maps are invalid. + enum class Liveness : int32_t { + kAlive = 0xCA11AB13, + kDead = 0xDEADBEEF, + }; + ThrottlingController(); ~ThrottlingController(); @@ -65,6 +72,9 @@ ThrottlingNetworkInterceptor* FindInterceptor(uint32_t net_log_source_id); + // TODO(https://crbug.com/960874): Debugging code. + void CheckValidThread(); + static ThrottlingController* instance_; using InterceptorMap = @@ -74,9 +84,11 @@ std::map<uint32_t /* net_log_source_id */, base::UnguessableToken /* throttling_profile_id */>; + // TODO(https://crbug.com/960874): Debugging code. + Liveness liveness_ = Liveness::kAlive; InterceptorMap interceptors_; NetLogSourceProfileMap net_log_source_profile_map_; - THREAD_CHECKER(thread_checker_); + base::ThreadCheckerImpl thread_checker_; DISALLOW_COPY_AND_ASSIGN(ThrottlingController); };
diff --git a/services/ws/public/cpp/gpu/client_gpu_memory_buffer_manager.cc b/services/ws/public/cpp/gpu/client_gpu_memory_buffer_manager.cc index 1b0f0128..499c2a35 100644 --- a/services/ws/public/cpp/gpu/client_gpu_memory_buffer_manager.cc +++ b/services/ws/public/cpp/gpu/client_gpu_memory_buffer_manager.cc
@@ -16,7 +16,6 @@ #include "mojo/public/cpp/system/buffer.h" #include "mojo/public/cpp/system/platform_handle.h" #include "services/service_manager/public/cpp/connector.h" -#include "services/ws/public/mojom/constants.mojom.h" #include "ui/gfx/buffer_format_util.h" namespace ws {
diff --git a/services/ws/public/cpp/gpu/gpu.cc b/services/ws/public/cpp/gpu/gpu.cc index 942dbeb..0a55112 100644 --- a/services/ws/public/cpp/gpu/gpu.cc +++ b/services/ws/public/cpp/gpu/gpu.cc
@@ -19,7 +19,6 @@ #include "services/service_manager/public/cpp/connector.h" #include "services/ws/public/cpp/gpu/client_gpu_memory_buffer_manager.h" #include "services/ws/public/cpp/gpu/context_provider_command_buffer.h" -#include "services/ws/public/mojom/constants.mojom.h" #include "services/ws/public/mojom/gpu.mojom.h" namespace ws {
diff --git a/services/ws/public/cpp/input_devices/input_device_controller_client.cc b/services/ws/public/cpp/input_devices/input_device_controller_client.cc index ccbd655..4decb45c 100644 --- a/services/ws/public/cpp/input_devices/input_device_controller_client.cc +++ b/services/ws/public/cpp/input_devices/input_device_controller_client.cc
@@ -8,7 +8,6 @@ #include "base/bind_helpers.h" #include "services/service_manager/public/cpp/connector.h" -#include "services/ws/public/mojom/constants.mojom.h" namespace ws { @@ -16,9 +15,8 @@ service_manager::Connector* connector, const std::string& service_name) : binding_(this) { - connector->BindInterface( - service_name.empty() ? mojom::kServiceName : service_name, - &input_device_controller_); + DCHECK(!service_name.empty()); + connector->BindInterface(service_name, &input_device_controller_); mojom::KeyboardDeviceObserverPtr ptr; binding_.Bind(mojo::MakeRequest(&ptr)); input_device_controller_->AddKeyboardDeviceObserver(std::move(ptr));
diff --git a/services/ws/public/mojom/BUILD.gn b/services/ws/public/mojom/BUILD.gn index 504d20d..3eb3b00 100644 --- a/services/ws/public/mojom/BUILD.gn +++ b/services/ws/public/mojom/BUILD.gn
@@ -7,14 +7,8 @@ mojom("mojom") { sources = [ - "event_injector.mojom", "gpu.mojom", - "remoting_event_injector.mojom", - "screen_provider_observer.mojom", - "user_activity_monitor.mojom", "window_manager.mojom", - "window_server_test.mojom", - "window_tree.mojom", "window_tree_constants.mojom", ] @@ -29,7 +23,6 @@ "//media/mojo/interfaces", "//mojo/public/mojom/base", "//services/viz/public/interfaces", - "//services/ws/public/mojom/ime", "//skia/public/interfaces", "//ui/base/ime/mojo", "//ui/base/mojo", @@ -55,19 +48,3 @@ "constants.mojom", ] } - -source_set("tests") { - testonly = true - - sources = [ - "ime/ime_struct_traits_unittest.cc", - ] - - deps = [ - "//base", - "//base/test:test_support", - "//services/ws/public/mojom/ime", - "//testing/gtest", - "//ui/gfx:test_support", - ] -}
diff --git a/services/ws/public/mojom/event_injector.mojom b/services/ws/public/mojom/event_injector.mojom deleted file mode 100644 index 4eaeb8c..0000000 --- a/services/ws/public/mojom/event_injector.mojom +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module ws.mojom; - -import "ui/events/mojo/event.mojom"; - -// An interface offered by the window service which allows clients to inject -// events. This class is mainly provided for tests, but is also used for timing -// (telemetry). -interface EventInjector { - // Takes an event and dispatches it as if it came from the native platform. - // Responds with false on bad |display_id| or bad |event|; true once the - // event has completed processing. - // - // If |event| is a LocatedEvent, then the coordinates must be in DIPs, and - // relative to the origin of the display identified by |display_id|. - InjectEvent(int64 display_id, ui.mojom.Event event) => (bool result); - - // Takes an event and dispatches it as if it came from the native platform. - // Similar to InjectEvent() but does not respond when processing is complete. - InjectEventNoAck(int64 display_id, ui.mojom.Event event); - - // Similar to InjectEventNoAck(), but skips event rewriters. - InjectEventNoAckNoRewriters(int64 display_id, ui.mojom.Event event); -};
diff --git a/services/ws/public/mojom/ime/BUILD.gn b/services/ws/public/mojom/ime/BUILD.gn deleted file mode 100644 index 9484f1f..0000000 --- a/services/ws/public/mojom/ime/BUILD.gn +++ /dev/null
@@ -1,20 +0,0 @@ -# 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. - -import("//mojo/public/tools/bindings/mojom.gni") - -mojom("ime") { - sources = [ - "ime.mojom", - ] - - public_deps = [ - "//mojo/public/mojom/base", - "//ui/base/ime/mojo", - "//ui/events/mojo:interfaces", - "//ui/gfx/geometry/mojo", - "//ui/gfx/range/mojo", - "//ui/platform_window/mojo:interfaces", - ] -}
diff --git a/services/ws/public/mojom/ime/OWNERS b/services/ws/public/mojom/ime/OWNERS deleted file mode 100644 index e75daf74..0000000 --- a/services/ws/public/mojom/ime/OWNERS +++ /dev/null
@@ -1,8 +0,0 @@ -per-file *_struct_traits*.*=set noparent -per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS - -per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS - -per-file *.typemap=set noparent -per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/services/ws/public/mojom/ime/ime.mojom b/services/ws/public/mojom/ime/ime.mojom deleted file mode 100644 index 04ca6de..0000000 --- a/services/ws/public/mojom/ime/ime.mojom +++ /dev/null
@@ -1,212 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module ws.mojom; - -import "mojo/public/mojom/base/text_direction.mojom"; -import "mojo/public/mojom/base/string16.mojom"; -import "ui/base/ime/mojo/ime_types.mojom"; -import "ui/events/mojo/event.mojom"; -import "ui/gfx/geometry/mojo/geometry.mojom"; -import "ui/gfx/range/mojo/range.mojom"; -import "ui/platform_window/mojo/text_input_state.mojom"; - -// Specifies where to display the candidate window. -enum CandidateWindowPosition { - // Candidate window follows the cursor. - kCursor, - - // Candidate window is locked to the beginning of the composition. - kComposition -}; - -struct CandidateWindowProperties { - // Number of candidates to display per page. - int32 page_size; - - // Should candidate window be rendered vertical or horizontal. - bool vertical; - - // Text that is shown at the bottom of the candidate window. - string auxiliary_text; - - // True to display auxiliary text, false to hide it. - bool auxiliary_text_visible; - - // Position and visibility of cursor in the candidate window. - int32 cursor_position; - bool cursor_visible; - - // Where to display the candidate window. - CandidateWindowPosition window_position; -}; - -// Represents a candidate window entry. -struct CandidateWindowEntry { - // Value of the candidate. - mojo_base.mojom.String16 value; - - // Short string displayed next to the candidate, often the shortcut key or - // index. - mojo_base.mojom.String16 label; - - // Additional text describing the candidate. - mojo_base.mojom.String16 annotation; - - // The usage or detailed description of the candidate. - mojo_base.mojom.String16 description_title; - mojo_base.mojom.String16 description_body; -}; - -// Represents the text input state of a client. -struct TextInputState { - ui.mojom.TextInputType text_input_type; - ui.mojom.TextInputMode text_input_mode; - mojo_base.mojom.TextDirection text_direction; - int32 text_input_flags; // A bitfield of ui::TextInputFlags. -}; - -// Cached input context information so that RemoteTextInputClient could support -// synchronous getters. -struct TextInputClientData { - gfx.mojom.Range? text_range; - mojo_base.mojom.String16? text; - bool has_composition_text; - gfx.mojom.Range? composition_text_range; - gfx.mojom.Range? editable_selection_range; - // Contains a boolean indicating the enabled state of each of the - // ui::TextEditCommands, where the index is the command. For example, - // edit_command_enabled[TextCommand::DELETE_BACKWARD] gives the enabled - // state of TextCommand::DELETE_BACKWARD. - array<bool>? edit_command_enabled; -}; - -// Detailed data of an IME session. -struct SessionDetails { - // State of the text input client. - TextInputState state; - - // Caret bounds of the text input client. - gfx.mojom.Rect caret_bounds; - - // Data of the text input client. - TextInputClientData data; - - // How the text input client was focused. - ui.mojom.FocusReason focus_reason; - - // ukm::SourceId for identifying the text input client. - int64 client_source_for_metrics; - - // Whether the text entered into this text input client should be used to - // improve IME suggestions. - bool should_do_learning; -}; - -// A service which provides the IMEDriver interface is responsible for doing -// the composition logic. After starting a session, it receives events from -// the client via the InputMethod interface, and sends composition events to -// the client via the TextInputClient. -interface IMEDriver { - StartSession(InputMethod& input_method_request, - TextInputClient client, - SessionDetails details); -}; - -// An IME driver register should register itself to Mus using the IMERegistrar -// interface. -interface IMERegistrar { - RegisterDriver(IMEDriver driver); -}; - -// A client sends updates to the IME driver using the InputMethod interface. -// This interface is provided by IME drivers, and also by Mus as a lightweight -// proxy between IME drivers and clients. -interface InputMethod { - // Called when the text input state of client is changed. - OnTextInputStateChanged(TextInputState text_input_state); - - // Client sends |caret_bounds| in focused window coordinates, - // Mus translates it to global coordinates and sends it to IME app. - OnCaretBoundsChanged(gfx.mojom.Rect caret_bounds); - - // Update the cached text input client data. - OnTextInputClientDataChanged(TextInputClientData data); - - // Called to process a key event. The callback function will be called to - // notify the client if the event was handled or not. A handled event may - // generate zero or more composition events which will be sent to the client - // using the "input method result" functions of TextInputClient interface. - ProcessKeyEvent(ui.mojom.Event key_event) => (bool handled); - - CancelComposition(); - - // Plumbs requests to show the virtual keyboard. - ShowVirtualKeyboardIfEnabled(); -}; - -// IME drivers send updates to clients using the TextInputClient interface. -interface TextInputClient { - // Functions corresponding to "input method result" functions of - // ui::TextInputClient. See comments for InputMethod::ProcessKeyEvent() for - // when these are called. - - // Sets composition text and attributes. See comments for - // ui::TextInputClient::SetCompositionText() for more details. - SetCompositionText(ui.mojom.CompositionText composition); - - // Converts current composition text into final content. - ConfirmCompositionText(); - - // Removes current composition text. - ClearCompositionText(); - - // Inserts a given text at the insertion point. Current composition text or - // selection will be removed. This method should never be called when the - // current text input type is TEXT_INPUT_TYPE_NONE. - InsertText(mojo_base.mojom.String16 text); - - // Inserts a single character at the insertion point. Unlike InsertText(), - // the character is not processed. See ui::TextInputClient::InsertChar() - // for more details. - InsertChar(ui.mojom.Event event); - - // Dispatch a key event after minimal processing by the IME. The results of - // the callback indicated whether the event was handled, and whether any - // further processing should be performed. That is, if |stopped_propagation| - // is true, IME does no further processing. - DispatchKeyEventPostIME(ui.mojom.Event event) => ( - bool handled, - bool stopped_propagation); - - // Ensure the caret is not in |rect|. |rect| is in dip screen coordinates - // and may extend beyond the bounds of this TextInputClient. - EnsureCaretNotInRect(gfx.mojom.Rect rect); - - // Selects the given UTF-16 based character range. Current composition text - // will be confirmed before selecting the range. - SetEditableSelectionRange(gfx.mojom.Range range); - - // Deletes contents in the given UTF-16 based character range. Current - // composition text will be confirmed before deleting the range. - DeleteRange(gfx.mojom.Range range); - - // Called whenever current keyboard layout or input method is changed. - OnInputMethodChanged(); - - // Called whenever the user requests to change the text direction and layout - // alignment of the current text box. - ChangeTextDirectionAndLayoutAlignment( - mojo_base.mojom.TextDirection direction); - - // Deletes the current selection plus the specified number of characters - // before and after the selection or caret. - ExtendSelectionAndDelete(uint32 before, uint32 after); - - // TODO(moshayedi): Add functions corresponding to ui::TextInputClient for: - // - Input context information - // - Document content operations - // - Miscellaneous functions - // crbug.com/631527. -};
diff --git a/services/ws/public/mojom/ime/ime.typemap b/services/ws/public/mojom/ime/ime.typemap deleted file mode 100644 index c2a508d6..0000000 --- a/services/ws/public/mojom/ime/ime.typemap +++ /dev/null
@@ -1,18 +0,0 @@ -# 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. - -mojom = "//services/ws/public/mojom/ime/ime.mojom" -public_headers = [ "//ui/base/ime/candidate_window.h" ] -traits_headers = [ "//services/ws/public/mojom/ime/ime_struct_traits.h" ] -sources = [ - "//services/ws/public/mojom/ime/ime_struct_traits.cc", -] -public_deps = [ - "//ui/base/ime", -] - -type_mappings = [ - "ws.mojom.CandidateWindowEntry=ui::CandidateWindow::Entry", - "ws.mojom.CandidateWindowProperties=ui::CandidateWindow::CandidateWindowProperty", -]
diff --git a/services/ws/public/mojom/ime/ime_struct_traits.cc b/services/ws/public/mojom/ime/ime_struct_traits.cc deleted file mode 100644 index a5bc13b..0000000 --- a/services/ws/public/mojom/ime/ime_struct_traits.cc +++ /dev/null
@@ -1,42 +0,0 @@ -// 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 "services/ws/public/mojom/ime/ime_struct_traits.h" - -#include "mojo/public/cpp/base/string16_mojom_traits.h" - -namespace mojo { - -// static -bool StructTraits<ws::mojom::CandidateWindowPropertiesDataView, - ui::CandidateWindow::CandidateWindowProperty>:: - Read(ws::mojom::CandidateWindowPropertiesDataView data, - ui::CandidateWindow::CandidateWindowProperty* out) { - if (data.is_null()) - return false; - if (!data.ReadAuxiliaryText(&out->auxiliary_text)) - return false; - out->page_size = data.page_size(); - out->is_vertical = data.vertical(); - out->is_auxiliary_text_visible = data.auxiliary_text_visible(); - out->cursor_position = data.cursor_position(); - out->is_cursor_visible = data.cursor_visible(); - out->show_window_at_composition = - data.window_position() == - ws::mojom::CandidateWindowPosition::kComposition; - return true; -} - -// static -bool StructTraits<ws::mojom::CandidateWindowEntryDataView, - ui::CandidateWindow::Entry>:: - Read(ws::mojom::CandidateWindowEntryDataView data, - ui::CandidateWindow::Entry* out) { - return !data.is_null() && data.ReadValue(&out->value) && - data.ReadLabel(&out->label) && data.ReadAnnotation(&out->annotation) && - data.ReadDescriptionTitle(&out->description_title) && - data.ReadDescriptionBody(&out->description_body); -} - -} // namespace mojo
diff --git a/services/ws/public/mojom/ime/ime_struct_traits.h b/services/ws/public/mojom/ime/ime_struct_traits.h deleted file mode 100644 index 0d7e959..0000000 --- a/services/ws/public/mojom/ime/ime_struct_traits.h +++ /dev/null
@@ -1,73 +0,0 @@ -// 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 SERVICES_WS_PUBLIC_MOJOM_IME_IME_STRUCT_TRAITS_H_ -#define SERVICES_WS_PUBLIC_MOJOM_IME_IME_STRUCT_TRAITS_H_ - -#include "services/ws/public/mojom/ime/ime.mojom-shared.h" -#include "ui/base/ime/candidate_window.h" - -namespace mojo { - -template <> -struct StructTraits<ws::mojom::CandidateWindowPropertiesDataView, - ui::CandidateWindow::CandidateWindowProperty> { - static int32_t page_size( - const ui::CandidateWindow::CandidateWindowProperty& p) { - return p.page_size; - } - static bool vertical(const ui::CandidateWindow::CandidateWindowProperty& p) { - return p.is_vertical; - } - static std::string auxiliary_text( - const ui::CandidateWindow::CandidateWindowProperty& p) { - return p.auxiliary_text; - } - static bool auxiliary_text_visible( - const ui::CandidateWindow::CandidateWindowProperty& p) { - return p.is_auxiliary_text_visible; - } - static int32_t cursor_position( - const ui::CandidateWindow::CandidateWindowProperty& p) { - return p.cursor_position; - } - static bool cursor_visible( - const ui::CandidateWindow::CandidateWindowProperty& p) { - return p.is_cursor_visible; - } - static ws::mojom::CandidateWindowPosition window_position( - const ui::CandidateWindow::CandidateWindowProperty& p) { - return p.show_window_at_composition - ? ws::mojom::CandidateWindowPosition::kComposition - : ws::mojom::CandidateWindowPosition::kCursor; - } - static bool Read(ws::mojom::CandidateWindowPropertiesDataView data, - ui::CandidateWindow::CandidateWindowProperty* out); -}; - -template <> -struct StructTraits<ws::mojom::CandidateWindowEntryDataView, - ui::CandidateWindow::Entry> { - static base::string16 value(const ui::CandidateWindow::Entry& e) { - return e.value; - } - static base::string16 label(const ui::CandidateWindow::Entry& e) { - return e.label; - } - static base::string16 annotation(const ui::CandidateWindow::Entry& e) { - return e.annotation; - } - static base::string16 description_title(const ui::CandidateWindow::Entry& e) { - return e.description_title; - } - static base::string16 description_body(const ui::CandidateWindow::Entry& e) { - return e.description_body; - } - static bool Read(ws::mojom::CandidateWindowEntryDataView data, - ui::CandidateWindow::Entry* out); -}; - -} // namespace mojo - -#endif // SERVICES_WS_PUBLIC_MOJOM_IME_IME_STRUCT_TRAITS_H_
diff --git a/services/ws/public/mojom/ime/ime_struct_traits_unittest.cc b/services/ws/public/mojom/ime/ime_struct_traits_unittest.cc deleted file mode 100644 index ad28ee1f..0000000 --- a/services/ws/public/mojom/ime/ime_struct_traits_unittest.cc +++ /dev/null
@@ -1,87 +0,0 @@ -// 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 "services/ws/public/mojom/ime/ime_struct_traits.h" - -#include <utility> - -#include "base/stl_util.h" -#include "base/strings/utf_string_conversions.h" -#include "mojo/public/cpp/base/string16_mojom_traits.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "services/ws/public/mojom/ime/ime.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace ws { - -namespace { - -class IMEStructTraitsTest : public testing::Test { - public: - IMEStructTraitsTest() {} - - private: - DISALLOW_COPY_AND_ASSIGN(IMEStructTraitsTest); -}; - -} // namespace - -TEST_F(IMEStructTraitsTest, CandidateWindowProperties) { - ui::CandidateWindow::CandidateWindowProperty input; - input.page_size = 7; - input.cursor_position = 3; - input.is_cursor_visible = true; - input.is_vertical = false; - input.show_window_at_composition = true; - input.auxiliary_text = "abcdefghij"; - input.is_auxiliary_text_visible = false; - - ui::CandidateWindow::CandidateWindowProperty output; - EXPECT_TRUE(mojom::CandidateWindowProperties::Deserialize( - mojom::CandidateWindowProperties::Serialize(&input), &output)); - - EXPECT_EQ(input.page_size, output.page_size); - EXPECT_EQ(input.cursor_position, output.cursor_position); - EXPECT_EQ(input.is_cursor_visible, output.is_cursor_visible); - EXPECT_EQ(input.is_vertical, output.is_vertical); - EXPECT_EQ(input.show_window_at_composition, - output.show_window_at_composition); - EXPECT_EQ(input.auxiliary_text, output.auxiliary_text); - EXPECT_EQ(input.is_auxiliary_text_visible, output.is_auxiliary_text_visible); - - // Reverse boolean fields and check we still serialize/deserialize correctly. - input.is_cursor_visible = !input.is_cursor_visible; - input.is_vertical = !input.is_vertical; - input.show_window_at_composition = !input.show_window_at_composition; - input.is_auxiliary_text_visible = !input.is_auxiliary_text_visible; - EXPECT_TRUE(mojom::CandidateWindowProperties::Deserialize( - mojom::CandidateWindowProperties::Serialize(&input), &output)); - - EXPECT_EQ(input.is_cursor_visible, output.is_cursor_visible); - EXPECT_EQ(input.is_vertical, output.is_vertical); - EXPECT_EQ(input.show_window_at_composition, - output.show_window_at_composition); - EXPECT_EQ(input.is_auxiliary_text_visible, output.is_auxiliary_text_visible); -} - -TEST_F(IMEStructTraitsTest, CandidateWindowEntry) { - ui::CandidateWindow::Entry input; - input.value = base::UTF8ToUTF16("entry_value"); - input.label = base::UTF8ToUTF16("entry_label"); - input.annotation = base::UTF8ToUTF16("entry_annotation"); - input.description_title = base::UTF8ToUTF16("entry_description_title"); - input.description_body = base::UTF8ToUTF16("entry_description_body"); - - ui::CandidateWindow::Entry output; - EXPECT_TRUE(mojom::CandidateWindowEntry::Deserialize( - mojom::CandidateWindowEntry::Serialize(&input), &output)); - - EXPECT_EQ(input.value, output.value); - EXPECT_EQ(input.label, output.label); - EXPECT_EQ(input.annotation, output.annotation); - EXPECT_EQ(input.description_title, output.description_title); - EXPECT_EQ(input.description_body, output.description_body); -} - -} // namespace ws
diff --git a/services/ws/public/mojom/ime/typemaps.gni b/services/ws/public/mojom/ime/typemaps.gni deleted file mode 100644 index 9785b15..0000000 --- a/services/ws/public/mojom/ime/typemaps.gni +++ /dev/null
@@ -1,5 +0,0 @@ -# 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. - -typemaps = [ "//services/ws/public/mojom/ime/ime.typemap" ]
diff --git a/services/ws/public/mojom/remoting_event_injector.mojom b/services/ws/public/mojom/remoting_event_injector.mojom deleted file mode 100644 index 7a276c1..0000000 --- a/services/ws/public/mojom/remoting_event_injector.mojom +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module ws.mojom; - -import "ui/gfx/geometry/mojo/geometry.mojom"; - -enum InjectedMouseButtonType { - kLeft, - kMiddle, - kRight, -}; - -// An interface offered by the window service which allows clients to inject -// events for remoting. This interfaces mirrors that of -// ui/events/SystemEventInjector. -interface RemotingEventInjector { - MoveCursorToLocationInPixels(gfx.mojom.PointF location); - - // If |down| is true, injects a mouse press, otherwise a mouse release. - InjectMousePressOrRelease(InjectedMouseButtonType button, bool down); - - InjectMouseWheelInPixels(int32 delta_x, int32 delta_y); - - // |native_key_code| corresponds to the native key-code from a dom-code. See - // DomCodeToNativeKeycode(). - InjectKeyEvent(int32 native_key_code, bool down, bool suppress_auto_repeat); -};
diff --git a/services/ws/public/mojom/screen_provider_observer.mojom b/services/ws/public/mojom/screen_provider_observer.mojom deleted file mode 100644 index 45304dd..0000000 --- a/services/ws/public/mojom/screen_provider_observer.mojom +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module ws.mojom; - -import "services/ws/public/mojom/window_tree_constants.mojom"; - -interface ScreenProviderObserver { - // Sent when the observer is added as well as any time the set of displays - // changes in any way. |displays| contains all known displays. If the system - // that WS is running on has an integrated display, for example a laptop - // internal display, then |internal_display_id| will be the corresponding - // display id. If there is no internal display then |internal_display_id| will - // be kInvalidDisplayID. |display_id_for_new_windows| is the display on which - // to place new top-level windows, usually the display on which a window was - // last activated. - OnDisplaysChanged(array<WsDisplay> displays, - int64 primary_display_id, - int64 internal_display_id, - int64 display_id_for_new_windows); -};
diff --git a/services/ws/public/mojom/user_activity_monitor.mojom b/services/ws/public/mojom/user_activity_monitor.mojom deleted file mode 100644 index f0cf7448..0000000 --- a/services/ws/public/mojom/user_activity_monitor.mojom +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module ws.mojom; - -interface UserActivityObserver { - OnUserActivity(); -}; - -interface UserIdleObserver { - enum IdleState { - ACTIVE, - IDLE, - }; - OnUserIdleStateChanged(IdleState new_state); -}; - -interface UserActivityMonitor { - // Notifies the observer of user activity at most once every - // |delay_between_notify_secs| seconds. - AddUserActivityObserver(uint32 delay_between_notify_secs, - UserActivityObserver observer); - - // Notifies the observer when user is idle for more than - // |idle_time_in_minutes| minutes. When the observer is first added, if the - // user has already been idle for |idle_time_in_minutes|, then - // OnUserIdleStateChanged(IDLE) is called on the observer, otherwise - // OnUserIdleStateChanged(ACTIVE) is called. - AddUserIdleObserver(uint32 idle_time_in_minutes, UserIdleObserver observer); -};
diff --git a/services/ws/public/mojom/window_server_test.mojom b/services/ws/public/mojom/window_server_test.mojom deleted file mode 100644 index 261aa94..0000000 --- a/services/ws/public/mojom/window_server_test.mojom +++ /dev/null
@@ -1,11 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -module ws.mojom; - -import "ui/events/mojo/event.mojom"; - -interface WindowServerTest { - EnsureClientHasDrawnWindow(string client_name) => (bool success); -};
diff --git a/services/ws/public/mojom/window_tree.mojom b/services/ws/public/mojom/window_tree.mojom deleted file mode 100644 index aca3358..0000000 --- a/services/ws/public/mojom/window_tree.mojom +++ /dev/null
@@ -1,709 +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. - -module ws.mojom; - -import "mojo/public/mojom/base/unguessable_token.mojom"; -import "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom"; -import "services/viz/public/interfaces/compositing/frame_sink_id.mojom"; -import "services/viz/public/interfaces/compositing/local_surface_id_allocation.mojom"; -import "services/viz/public/interfaces/compositing/surface_info.mojom"; -import "services/ws/public/mojom/window_manager.mojom"; -import "services/ws/public/mojom/screen_provider_observer.mojom"; -import "services/ws/public/mojom/window_tree_constants.mojom"; -import "ui/base/ime/mojo/ime.mojom"; -import "ui/base/mojo/cursor.mojom"; -import "ui/base/mojo/ui_base_types.mojom"; -import "ui/events/mojo/event.mojom"; -import "ui/events/mojo/event_constants.mojom"; -import "ui/gfx/geometry/mojo/geometry.mojom"; -import "ui/gfx/image/mojo/image.mojom"; -import "ui/gfx/mojo/transform.mojom"; -import "ui/platform_window/mojo/text_input_state.mojom"; - -// Windows are identified by a uint64. The upper 32 bits are the id assigned to -// the client by the Window Service, and the lower 32 an id assigned by the -// client. Windows created by the client supply a client id of 0, which the -// Window Service maps appropriately. For clients that see Windows created by -// another client, the upper 32 bits are set to identify the other client. -// -// The root window is identified with a connection id of 0, and value of 1. -// -// Most functions to the WindowTree take a change_id parameter. When -// WindowTree completes processing of a function WindowTree calls -// WindowTreeClient::OnChangeCompleted() with the change_id supplied by the -// client and the result of the function. This allows the client to track -// whether the call succeeded or not. Calls are done via the client interface -// rather than a callback to ensure ordering. The server does not interpret the -// change id in anyway, it is up to the client to assign a value and use it. -// Generally the change id is an ever increasing integer. -// -// Event processing happens in the following order: -// . The event is sent to the accelerator registered for the PRE_TARGET. If -// the client consumes the event, matching event observers are notified and -// processing stops. If the client does not consume the event processing -// continues. -// . Target window (lookup of the target window depends upon the event type) and -// matching event observers are notified at the same time. The target is only -// notified once, even if it has a matching event observer registered. If the -// target consumes the event, processing stops. -// . Accelerator registered for POST_TARGET. No response is expected from the -// client for the POST_TARGET and processing of the next continues -// immediately. -interface WindowTree { - // Creates a new window with the specified id. It is up to the client to - // ensure the id is unique to the connection (the id need not be globally - // unique). Additionally the connection id (embedded in |window_id|) must - // match that of the connection. - // Errors: - // ERROR_CODE_VALUE_IN_USE: a window already exists with the specified id. - // ERROR_CODE_ILLEGAL_ARGUMENT: The connection part of |window_id| does not - // match the connection id of the client. - NewWindow(uint32 change_id, - uint64 window_id, - map<string, array<uint8>>? properties); - - // Requests the WindowManager to create a new top level window. On success - // OnTopLevelCreated() is called with the WindowData for the new window. On - // failure OnChangeCompleted() is called. - NewTopLevelWindow(uint32 change_id, - uint64 window_id, - map<string, array<uint8>> properties); - - // Deletes a window. This does not recurse. No hierarchy change notifications - // are sent as a result of this. Only the connection that created the window - // can delete it. DeleteWindow() may also be used to remove a window as an - // embed root from the client. When DeleteWindow() is used to remove an embed - // root, the client no longer has access to the embed root. The embedder of - // the root is notified of the change via OnEmbeddedAppDisconnected(). - DeleteWindow(uint32 change_id, uint64 window_id); - - // Requests input event capture for the given |window_id|. Capture is only - // allowed if the window is processing an event. When a window gains capture, - // current input events are canceled. The given window will receive all - // subsequent input until an alternate window is set via SetCapture, or - // ReleaseCapture is called for |window_id|. OnCaptureChanged() is called to - // notify of capture changing (as long as the client did not initiate the - // change). - SetCapture(uint32 change_id, uint64 window_id); - - // Releases input event capture for the given |window_id|. This does nothing - // if |window_id| does not currently have capture. - ReleaseCapture(uint32 change_id, uint64 window_id); - - // Start observing global events matching the supplied |types|, even if they - // are not targeted at the requesting client. Events that would normally be - // sent to the requesting client (ie. the event target is this window tree) - // are sent to OnWindowInputEvent() with |matches_event_observer| set to true. - // - // Clients should limit the requested types and the duration of observation, - // as there is a system-wide perf/battery penalty, especially for mouse moves. - // - // See class description for details on event delivery. - ObserveEventTypes(array<ui.mojom.EventType> types); - - // Sets the specified bounds of the specified window. The window will paint - // the frame in the provided |local_frame_id|, if any. - // |local_surface_id_allocation| need only be supplied for roots. - // For top-levels, clients may supply a null LocalSurfaceIdAllocation, before - // OnTopLevelCreated() is called (clients receive the initial - // LocalSurfaceIdAllocation in OnTopLevelCreated()). While clients may supply - // a LocalSurfaceIdAllocation for top-levels, they are only allowed to - // change the child-sequence number portion of the id. Supplying a different - // embed token results in failure, and changes to the parent sequence number - // are ignored. - // |bounds| are in DIPs. - SetWindowBounds( - uint32 change_id, - uint64 window_id, - gfx.mojom.Rect bounds, - viz.mojom.LocalSurfaceIdAllocation? local_surface_id_allocation); - - // Updates the LocalSurfaceIdAllocation for a window from the child. Does - // nothing if |window_id| does not identify a top-level. See comment in - // SetWindowBounds() for allowable values of |local_surface_id_allocation|. - UpdateLocalSurfaceIdFromChild( - uint64 window_id, - viz.mojom.LocalSurfaceIdAllocation local_surface_id_allocation); - - // Asks the server to generate a new LocalSurfaceId for a window. The server - // responds with the new LocalSurfaceId by way of OnWindowBoundsChanged(). - // This is only useful for top-levels. - AllocateLocalSurfaceId(uint64 window_id); - - SetWindowTransform(uint32 change_id, - uint64 window_id, - gfx.mojom.Transform transform); - - // Sets the client area of the specified window. The client area is specified - // by way of insets. Everything outside of the insets, and not in - // |additional_client_areas| is considered non-client area. - // TODO(sky): convert additional_client_areas to a path. - SetClientArea(uint64 window_id, - gfx.mojom.Insets insets, - array<gfx.mojom.Rect>? additional_client_areas); - - // Insets the hit test of a window by the specified values. The insets must be - // positive (or zero). |mouse| applies to events originating from the mouse, - // and |touch| from a non-mouse pointer device (such as tap). - SetHitTestInsets(uint64 window_id, - gfx.mojom.Insets mouse, - gfx.mojom.Insets touch); - - // Specifies the shape of the window. The region outside of the shape becomes - // transparent and should be considered to be outside of the widget, so - // underlying window will be targeted. Each element of |shape| is relative to - // the window's coordinate. Empty means to reset the settings, so the normal - // rectangular region will be used. - SetShape(uint64 window_id, array<gfx.mojom.Rect> shape); - - // Called by clients that want to accept drag and drops. Windows default to - // this being disabled; a window must actively opt-in to receiving OnDrag*() - // calls. - SetCanAcceptDrops(uint64 window_id, bool accepts_drops); - - // Sets the visibility of the specified window to |visible|. Connections are - // allowed to change the visibility of any window they have created, as well - // as any of their roots. - SetWindowVisibility(uint32 change_id, uint64 window_id, bool visible); - - // Sets an individual named property. Setting an individual property to null - // deletes the property. - SetWindowProperty(uint32 change_id, - uint64 window_id, - string name, - array<uint8>? value); - - // Sets the opacity of the specified window to |opacity|. - SetWindowOpacity(uint32 change_id, uint64 window_id, float opacity); - - // Sets the transparent status of the specified window to |transparent|. - SetWindowTransparent(uint32 change_id, uint64 window_id, bool transparent); - - // Attaches a CompositorFrameSink to a particular window. - AttachCompositorFrameSink( - uint64 window_id, - viz.mojom.CompositorFrameSink& compositor_frame_sink, - viz.mojom.CompositorFrameSinkClient client); - - // Reparents a window. - // This fails for any of the following reasons: - // . |parent| or |child| does not identify a valid window. - // . |child| is an ancestor of |parent|. - // . |child| is already a child of |parent|. - // - // This may result in a connection getting OnWindowDeleted(). See - // RemoveWindowFromParent for details. - AddWindow(uint32 change_id, uint64 parent, uint64 child); - - // Removes a window from its current parent. This fails if the window is not - // valid or the window already has no parent. - // - // Removing a window from a parent may result in OnWindowDeleted() being sent - // to other connections. For example, connection A has windows 1 and 2, with 2 - // a child of 1. Connection B has a root 1. If 2 is removed from 1 then B gets - // OnWindowDeleted(). This is done as window 2 is effectively no longer - // visible to connection B. - RemoveWindowFromParent(uint32 change_id, uint64 window_id); - - // Ties the lifetime of |transient_window_id| to the lifetime of |window_id|. - // This also places |transient_window_id| on top of |window_id|. - // This fails for any of the following reasons: - // . |window_id| or |transient_window_id| does not identify a valid window. - // . |transient_window_id| is an ancestor of |window_id|. - // . |transient_window_id| is modal to system. - AddTransientWindow(uint32 change_id, - uint64 window_id, - uint64 transient_window_id); - - // Decouples the lifetime of |transient_window_id| from its transient parent. - // This does not change transient window's position in the window hierarchy. - RemoveTransientWindowFromParent(uint32 change_id, uint64 transient_window_id); - - // Changes modality type of |window_id|. This releases capture if necessary. - // This fails for any of the following reasons: - // . |window_id| does not identify a valid window. - // . Client does not have a valid user id (i.e., it is an embedded app). - SetModalType(uint32 change_id, uint64 window_id, ui.mojom.ModalType type); - - // Reorders a window in its parent, relative to |relative_window_id| according - // to |direction|. Only the connection that created the window's parent can - // reorder its children. - ReorderWindow(uint32 change_id, - uint64 window_id, - uint64 relative_window_id, - OrderDirection direction); - - // Returns the windows comprising the tree starting at |window_id|. - // |window_id| is the first result in the return value, unless |window_id| is - // invalid, in which case an empty vector is returned. The windows are visited - // using a depth first search (pre-order). - GetWindowTree(uint64 window_id) => (array<WindowData> windows); - - // A connection may grant access to another connection by way of Embed(). - // Embed() results in the supplied WindowTreeClient being configured with a - // root window of |window_id|. The supplied WindowTreeClient may create child - // windows and do other various tree operations (including Embed()), but does - // not see nor have access to any of the windows above the embed point. - // - // The caller must have created |window_id|. If not the request fails and the - // response is false. - // - // The embedder can dictate the behaviour of the embedded client by setting - // the appropriate embed flags (e.g. kEmbedFlagEmbedderInterceptsEvents). - // - // When a connection embeds a WindowTreeClient the originating connection no - // longer has privileges to access or see any of the children of the window. - // If the window had existing children the children are removed. The - // WindowManager gets to see the whole tree. - // - // A window may only have one embedding in it at a time. Subsequent calls to - // Embed() for the same window result in the currently embedded - // WindowTreeClient being removed. The embedded app is told this by way of - // OnUnembed(), which is followed by OnWindowDeleted() (as the connection no - // longer has access to the window). - // - // The embedder can detect when the embedded app disconnects by way of - // OnEmbeddedAppDisconnected(). - // - // The callback returns whether the embedding was successful. - Embed(uint64 window_id, WindowTreeClient client, uint32 embed_flags) - => (bool success); - - // Schedules a future call to Embed() using the returned token. This is used - // when two clients need to work together to complete an embedding without - // passing the WindowTreeClient between the two. This ensures a client isn't - // able to spoof another client (say by directly passing events to the - // client). - // - // For example, client A embeds client B in a window. Client A wants client B - // to embed a WindowTreeClient in a window created by client B. This can be - // accomplished by client A calling ScheduleEmbed() and then passing the - // token returned from ScheduleEmbed() to client B (using a separate pipe) so - // that client B may call EmbedUsingToken(). - ScheduleEmbed(WindowTreeClient client) - => (mojo_base.mojom.UnguessableToken token); - - // Creates an UnguessableToken for use in a future call, by another client, to - // EmbedUsingToken(). - // - // The following example shows how to use this api. Client A wants client B - // to embed it in a window created by client B. - // 1. Client A calls ScheduleEmbedForExistingClient() to get a token. - // 2. Client A passes the token to client B. This communication is done using - // an additional channel, outside of WindowTree/WindowTreeClient. - // 3. Client B calls EmbedUsingToken(). - // 4. Client A receives OnEmbedFromToken() with the token from step 1. - // - // |window_id| is the id used for the window once EmbedUsingToken() is called. - // More specifically, when OnEmbedFromToken() is called |window_id| is the id - // of the window identified in the WindowData. - ScheduleEmbedForExistingClient(uint32 window_id) => ( - mojo_base.mojom.UnguessableToken token); - - // Pair with ScheduleEmbed() or ScheduleEmbedForExistingClient() to complete - // an embedding, see them for details. - EmbedUsingToken(uint64 window_id, - mojo_base.mojom.UnguessableToken token, - uint32 embed_flags) - => (bool success); - - // Attaches/unattaches a FrameSinkId to this window. A window can only have - // a single frame-sink-id attached to it. - AttachFrameSinkId(uint64 window_id, - viz.mojom.FrameSinkId frame_sink_id); - UnattachFrameSinkId(uint64 window_id); - - // Sets focus to the specified window, use 0 to clear focus. For a window to - // get focus the following has to happen: the window is drawn, the window has - // been marked as focusable (see SetCanFocus()) and the window is in a - // container the WindowManager has identified as allowing activation - // (see WindowManagerClient::AddActivationParent()). - SetFocus(uint32 change_id, uint64 window_id); - - // Marks the specified window as being able to receive focus. - SetCanFocus(uint64 window_id, bool can_focus); - - // Sets the cursor when the pointer is inside |window_id|. - SetCursor(uint32 change_id, uint64 window_id, ui.mojom.Cursor cursor); - - // Set text input state for the given window. - SetWindowTextInputState(uint64 window_id, ui.mojom.TextInputState state); - - // Set the input method editor UI (software keyboard, etc) visibility. - // If state is non-null, the specified window's text input state is updated. - // Otherwise the existing state is used. - SetImeVisibility(uint64 window_id, - bool visible, - ui.mojom.TextInputState? state); - - // Sets the EventTargetingPolicy. See EventTargetingPolicy for details. - SetEventTargetingPolicy(uint64 window_id, EventTargetingPolicy policy); - - // See documentation for WindowTreeClient::OnWindowInputEvent(). - OnWindowInputEventAck(uint32 event_id, EventResult result); - - // If the current focus is (or is a child of) |window_id|, requests that the - // window manager change the focus to the next activatable window. - DeactivateWindow(uint64 window_id); - - // Stacks the window |above_id| above |below_id|. These two windows must - // share the same parent. This function is intended for use with top-levels - // only. For non-top-levels, use ReorderWindow(). - // TODO(sky): unify this and ReorderWindow(). https://crbug.com/850133. - StackAbove(uint32 change_id, uint64 above_id, uint64 below_id); - - // Stacks the window above all sibling windows. - StackAtTop(uint32 change_id, uint64 window_id); - - // Requests a window manager specific interface. |name| is the name of the - // interface. This function is typed to WindowManager, but that's purely - // by necessity. This function is used to request *any* interface known to - // the environment hosting the window service. If |name| is not the name of - // an interface known to the environment hosting the window service, - // |window_manager| is closed. - BindWindowManagerInterface(string name, - associated WindowManager& window_manager); - - // Returns a shared memory segment that contains two 16-bit ints packed into a - // single Atomic32, which represent the current location of the mouse cursor - // where the location is (x << 16) | y. - GetCursorLocationMemory() => (handle<shared_buffer> cursor_buffer); - - // Tells the window manager to start moving or resizing the window. - // OnChangeCompleted is called on whether the move was canceled. Because - // there's a delay between when a client sends this message and when the - // window manager starts acting on it, pass the cursor location at the start - // of the move. |hit_test| specifies the type of the session; kCaption for - // moving. - PerformWindowMove(uint32 change_id, uint64 window_id, MoveLoopSource source, - gfx.mojom.Point cursor, ui.mojom.HitTest hit_test); - - // Tells the window manager to cancel any in progress window move started with - // StartWindowMove() and to revert the window bounds to how they were. - CancelWindowMove(uint64 window_id); - - // Called by the client to start a drag operation. |source_window_id| is the - // source window, |screen_location| is what the source thinks their location - // of the pointer which started the drag is, |drag_data| is the entire set of - // mime to raw data mapping. |drag_image| and |drag_image_offset| describe - // an image to hold behind the cursor which represents the data on the - // clipboard. We send this during the start of the drag because most views - // clients will try to read all this data on first entry. - PerformDragDrop(uint32 change_id, - uint64 source_window_id, - gfx.mojom.Point screen_location, - map<string, array<uint8>> drag_data, - gfx.mojom.ImageSkia? drag_image, - gfx.mojom.Vector2d drag_image_offset, - uint32 drag_operation, - ui.mojom.PointerKind source); - - // Called by the client to cancel any in progress drag drop operation. This - // will result in a change completed for the underlying change. - CancelDragDrop(uint64 window_id); - - // Called by the client to start a session of observing the topmost window - // under the cursor or touch point. Once called, OnTopmostWindowChanged() is - // called on the client whenever the topmost window changes. |source| - // specifies what type of located events should be observed (mouse or touch), - // and |window_id| specifies the initial target of the located event. - ObserveTopmostWindow(MoveLoopSource source, uint64 window_id); - - // Called by the client to request stopping the ongoing session of observing - // the topmost window under the cursor. - StopObservingTopmostWindow(); - - // Sets the resize shadow for |hit_test| to the specified window. It hides - // the shadow when kNowhere is set. - SetWindowResizeShadow(uint64 window_id, ui.mojom.HitTest hit_test); - - // Called by the client to cancel active touch events. not_cancelled_window_id - // is a window ID, and that window is excluded from cancelling. When - // not_cancelled_window_id is invalid, active touch events should be cancelled - // on all windows. - CancelActiveTouchesExcept(uint64 not_cancelled_window_id); - - // Called by the client to cancel active touches on |window_id|. - CancelActiveTouches(uint64 window_id); - - // Called by the client to transfer the gesture stream from the window of - // |current_id| to the window of |new_id|. If |should_cancel| is set, then - // cancel events are also dispatched to |current_id|. Both |current_id| and - // |new_id| need to be valid window ID created by the client. This operation - // is not allowed for embedded clients. - TransferGestureEventsTo(uint64 current_id, uint64 new_id, bool should_cancel); - - // Called by the client to start occlusion tracking for a window. - TrackOcclusionState(uint64 window_id); - - // Called by the client to pause occlusion states computation when there are - // massive window changes (such as a hierarchy change, or multiple window - // visibility change) to avoid unnecessary occlusion state updates. Server - // will re-compute the occlusion state after a balancing - // UnpauseWindowOcclusionTracking call. - PauseWindowOcclusionTracking(); - - // Called by the client the resume occlusion states computation. When - // all outstanding pause requests are cleared, server will re-compute - // occlusion states for the tracked windows and send back updates. - UnpauseWindowOcclusionTracking(); - - // Called by the client every time the focus changes, to build the connection - // between the client and the IME. And Window Service makes sure that only - // focused client can have the connection. - ConnectToImeEngine(ime.mojom.ImeEngine& engine_request, - ime.mojom.ImeEngineClient client); -}; - -// Changes to windows are not sent to the connection that originated the -// change. For example, if connection 1 changes the bounds of a window by -// calling SetWindowBounds(), connection 1 does not receive -// OnWindowBoundsChanged(). -interface WindowTreeClient { - // Sent when clients establishes a connection to the WindowService. - // |client_id| gives the unique id for the client. This value is generally - // only useful for debugging. - OnClientId(uint32 client_id); - - // Invoked when the client application has been embedded at |root|. - // See Embed() on WindowTree for more details. |tree| will be a handle back to - // the window manager service, unless the connection is to the root connection - // in which case it will be null. |parent_drawn| is true if roots parent is - // drawn, see OnParentDrawnStateChanged() for details. |display_id| identifies - // the display this root window is on. If the embedded window has a size, - // |local_surface_id| identifies the ID to use to submit CompositorFrames. - OnEmbed(WindowData root, - WindowTree? tree, - int64 display_id, - uint64 focused_window, - bool parent_drawn, - viz.mojom.LocalSurfaceIdAllocation? local_surface_id_allocation); - - // See description in ScheduleEmbedForExistingClient() for details on this. - // Supplied arguments match that of OnEmbed(). - OnEmbedFromToken( - mojo_base.mojom.UnguessableToken token, - WindowData root, - int64 display_id, - viz.mojom.LocalSurfaceIdAllocation? local_surface_id_allocation); - - // Invoked when the application embedded at |window| is disconnected. In other - // words the embedded app closes the connection to the server. This is called - // on the connection that created |window| as well as any ancestors that have - // the embed root policy. - OnEmbeddedAppDisconnected(uint64 window); - - // Sent when another connection is embedded in the Window this connection was - // previously embedded in. See Embed() for more information. - OnUnembed(uint64 window); - - // Sent when capture changes. This is not sent if the client initiated the - // change. - OnCaptureChanged(uint64 new_capture, uint64 old_capture); - - // This is called on the client that initiated a call to Embed(), and informs - // the owner (embedder) of the new FrameSinkId of the window (embedding - // results in changing the FrameSinkId). - OnFrameSinkIdAllocated(uint64 window, viz.mojom.FrameSinkId frame_sink_id); - - // Called in response to NewTopLevelWindow() successfully completing. - // |parent_drawn| is true if the parent of the window is drawn, see - // OnDrawnStateChanged() for details. |display_id| identifies the display this - // window is on. - OnTopLevelCreated( - uint32 change_id, - WindowData data, - int64 display_id, - bool parent_drawn, - viz.mojom.LocalSurfaceIdAllocation local_surface_id_allocation); - - // Invoked when a window's bounds have changed. |state| is supplied for roots, - // and SHOW_STATE_DEFAULT for non-roots. It allows the client to - // simultaneously update both bounds and show state, e.g. after a maximize - // operation. |local_surface_id_allocation| is only supplied for roots. - OnWindowBoundsChanged( - uint64 window, - gfx.mojom.Rect new_bounds, - ui.mojom.WindowShowState state, - viz.mojom.LocalSurfaceIdAllocation? local_surface_id_allocation); - - OnWindowTransformChanged(uint64 window, - gfx.mojom.Transform new_transform); - - OnTransientWindowAdded(uint64 window_id, - uint64 transient_window_id); - - OnTransientWindowRemoved(uint64 window_id, - uint64 transient_window_id); - - // Invoked when a change is done to the hierarchy. A value of 0 is used to - // identify a null window. For example, if the old_parent is NULL, 0 is - // supplied. - // If |window| was not visible to this client, but is visible now because - // |new_parent| is visible to this client, then |windows| contains details - // about |window|, and all its descendants. |windows| includes any windows - // the client may already know about, but did not know the parent because - // the parent was previously not visible to this client. - // This is not sent for hierarchy changes of windows not known to this client - // or not attached to the tree. - OnWindowHierarchyChanged(uint64 window, - uint64 old_parent, - uint64 new_parent, - array<WindowData> windows); - - // Invoked when the order of windows within a parent changes. - OnWindowReordered(uint64 window_id, - uint64 relative_window_id, - OrderDirection direction); - - // Invoked when a window is deleted. - OnWindowDeleted(uint64 window); - - // Invoked when the visibility of the specified window changes. - OnWindowVisibilityChanged(uint64 window, bool visible); - - // Invoked when the window moves to a new display. This is only called on - // a top-level window or an embedded root. - OnWindowDisplayChanged(uint64 window, int64 display_id); - - // Invoked when the drawn state of |window|'s parent changes. The drawn state - // is determined by the visibility of a Window and the Windows ancestors. A - // Window is drawn if all ancestors are visible, not drawn if any ancestor is - // hidden. - // - // The initial drawn state is communicated by way of OnTopLevelCreated() or - // OnEmbed(). - // - // This function is only called for root Windows as the drawn state of all - // other windows can be determined from their parent. - OnWindowParentDrawnStateChanged(uint64 window, bool drawn); - - // Invoked when a window property is changed. If this change is a removal, - // |new_data| is null. - OnWindowSharedPropertyChanged(uint64 window, - string name, - array<uint8>? new_data); - - // Invoked when an event is targeted at the specified window. The client must - // call WindowTree::OnWindowInputEventAck() with the same |event_id| to ack - // that the event has been processed, and with an EventResult value to notify - // if the event was consumed. |matches_event_observer| is true if the event - // also matches the requested types passed via ObserveEventTypes(). The client - // must respond to ack these events, regardless of |matches_event_observer|. - OnWindowInputEvent(uint32 event_id, - uint64 window, - int64 display_id, - ui.mojom.Event event, - bool matches_event_observer); - - // Called when an event not targeted at this client is observed, matching the - // event types passed to ObserveEventTypes(); see that function for details. - // Located events are always passed with the locations in screen coordinates. - // The client should not respond to ack these events. - OnObservedInputEvent(ui.mojom.Event event); - - // Called in two distinct cases: when a window known to the connection gains - // focus, or when focus moves from a window known to the connection to a - // window not known to the connection. In the later case |focused_window_id| - // is 0. As with other functions this is only called if the client did not - // initiate the change. - OnWindowFocused(uint64 focused_window_id); - - OnWindowCursorChanged(uint64 window_id, ui.mojom.Cursor cursor); - - // Called when the mouse cursor enters a window on this connection for the - // first time, providing a list of available mime types. We want to send this - // set of data only one time, so this isn't part of OnDragEnter(), which - // occurs every time the mouse enters a window. - OnDragDropStart(map<string, array<uint8>> drag_data); - - // Called when the mouse cursor enters a window that has opted into accepting - // drags through SetAcceptsDrags(), providing a list of available mime types. - // |location_in_root| is the location relative to the embed root of |window|. - // |location| is the location relative to |window|. - // If |window| is a top-level or embed root, then |location_in_root| is the - // same as |location|. Callback is supplied the supported operations. - OnDragEnter(uint64 window, - uint32 key_state, - gfx.mojom.PointF location_in_root, - gfx.mojom.PointF location, - uint32 effect_bitmask) => (uint32 supported_op_bitmask); - - // Called when the pointer moves over the window after the initial DragEnter. - // Returns a bitmask of the supported operations at this location. See - // OnDragEnter() for details on coordinates. - OnDragOver(uint64 window, - uint32 key_state, - gfx.mojom.PointF location_in_root, - gfx.mojom.PointF location, - uint32 effect_bitmask) => (uint32 supported_op_bitmask); - - // Called when the pointer leaves a window or if the drop is canceled. - OnDragLeave(uint64 window); - - // Called when the drop occurs on a window. Returns the action taken. See - // OnDragEnter() for details on coordinates. - OnCompleteDrop(uint64 window, - uint32 key_state, - gfx.mojom.PointF location_in_root, - gfx.mojom.PointF location, - uint32 effect_bitmask) => (uint32 action_taken); - - // Called on the client that requested PerformDragDrop() to return which drag - // action was completed. This is called instead of OnChangeCompleted(). - OnPerformDragDropCompleted(uint32 change_id, - bool success, - uint32 action_taken); - - // Called after OnCompleteDrop completes for every connection which received - // an OnDragDropStart() message. This signals that a client can forget the - // |drag_data| passed in via the first message. - OnDragDropDone(); - - // Called when the topmost window under the cursor/touch changes. The client - // receives at most two IDs for the topmost windows. The first one is for the - // topmost window. The second one is optionally for the second topmost window - // if the first one happens to be the current event target. The second one - // will be used by the client when they want to ignore the event target. - // Each ID can be 0 when the window is not hosted by the client. - OnTopmostWindowChanged(array<uint64> topmost_ids); - - // A change initiated from the client has completed. See description of - // change ids for details. - OnChangeCompleted(uint32 change_id, bool success); - - // The WindowManager is requesting the specified window to close. If the - // client allows the change it should delete the window. - RequestClose(uint64 window_id); - - // Requests the ScreenProviderObserver from the client. See - // ScreenProviderObserver for details. - GetScreenProviderObserver(associated ScreenProviderObserver& observer); - - // Called to send occlusion changes to client. |occlusion_changes| contains - // the changed info, with window id as its key and new occlusion state as its - // data. See also TrackOcclusionState on WindowTree. - OnOcclusionStatesChanged(map<uint64, OcclusionState> occlusion_changes); - - // Cancels the ongoing touch gesture recognitions and clears related gesture - // recognition state of the window of |window_id| in the client. - CleanupGestureState(uint64 window_id); - - // Called when the window manager may start resizing a window by a user - // gesture. For example, if the user clicks on a window-resize handle this may - // be called. This is followed by OnWindowResizeLoopEnded() when the loop is - // done. This function is only called for top-levels. - // OnWindowResizeLoopEnded() may not be called if the window is destroyed - // during the loop. - OnWindowResizeLoopStarted(uint64 window_id); - OnWindowResizeLoopEnded(uint64 window_id); -}; - -// Mus provides this interface as a way for clients to connect and obtain a -// WindowTree handle with a supplied WindowTreeClient handle. The -// WindowTreeClient has no roots, use NewTopLevelWindow() to create one. -interface WindowTreeFactory { - CreateWindowTree(WindowTree& tree_request, WindowTreeClient client); -};
diff --git a/storage/browser/fileapi/file_system_context_unittest.cc b/storage/browser/fileapi/file_system_context_unittest.cc index 8cf9e34..b579dcd6 100644 --- a/storage/browser/fileapi/file_system_context_unittest.cc +++ b/storage/browser/fileapi/file_system_context_unittest.cc
@@ -44,10 +44,9 @@ GURL CreateRawFileSystemURL(const std::string& type_str, const std::string& fs_id) { - std::string url_str = base::StringPrintf( - "filesystem:http://chromium.org/%s/%s/root/file", - type_str.c_str(), - fs_id.c_str()); + std::string url_str = + base::StringPrintf("filesystem:http://chromium.org/%s/%s/root/file", + type_str.c_str(), fs_id.c_str()); return GURL(url_str); } @@ -111,26 +110,21 @@ // Cracking system external mount and isolated mount points should work. std::string isolated_name = "root"; - std::string isolated_id = + IsolatedContext::ScopedFSHandle isolated_fs = IsolatedContext::GetInstance()->RegisterFileSystemForPath( - storage::kFileSystemTypeNativeLocal, - std::string(), - base::FilePath(DRIVE FPL("/test/isolated/root")), - &isolated_name); + storage::kFileSystemTypeNativeLocal, std::string(), + base::FilePath(DRIVE FPL("/test/isolated/root")), &isolated_name); + std::string isolated_id = isolated_fs.id(); // Register system external mount point. ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( - "system", - storage::kFileSystemTypeNativeLocal, - FileSystemMountOption(), + "system", storage::kFileSystemTypeNativeLocal, FileSystemMountOption(), base::FilePath(DRIVE FPL("/test/sys/")))); FileSystemURL cracked_isolated = file_system_context->CrackURL( CreateRawFileSystemURL("isolated", isolated_id)); ExpectFileSystemURLMatches( - cracked_isolated, - GURL(kTestOrigin), - storage::kFileSystemTypeIsolated, + cracked_isolated, GURL(kTestOrigin), storage::kFileSystemTypeIsolated, storage::kFileSystemTypeNativeLocal, base::FilePath(DRIVE FPL("/test/isolated/root/file")) .NormalizePathSeparators(), @@ -143,9 +137,7 @@ CreateRawFileSystemURL("external", "system")); ExpectFileSystemURLMatches( - cracked_external, - GURL(kTestOrigin), - storage::kFileSystemTypeExternal, + cracked_external, GURL(kTestOrigin), storage::kFileSystemTypeExternal, storage::kFileSystemTypeNativeLocal, base::FilePath(DRIVE FPL("/test/sys/root/file")) .NormalizePathSeparators(), @@ -163,9 +155,7 @@ // Register system external mount point. ASSERT_TRUE(mount_points->RegisterFileSystem( - "system", - storage::kFileSystemTypeNativeLocal, - FileSystemMountOption(), + "system", storage::kFileSystemTypeNativeLocal, FileSystemMountOption(), base::FilePath(DRIVE FPL("/test/sys/")))); scoped_refptr<FileSystemContext> file_system_context( @@ -180,9 +170,7 @@ CreateRawFileSystemURL("external", "system")); ExpectFileSystemURLMatches( - cracked_external, - GURL(kTestOrigin), - storage::kFileSystemTypeExternal, + cracked_external, GURL(kTestOrigin), storage::kFileSystemTypeExternal, storage::kFileSystemTypeNativeLocal, base::FilePath(DRIVE FPL("/test/sys/root/file")) .NormalizePathSeparators(), @@ -201,36 +189,29 @@ // Register an isolated mount point. std::string isolated_file_system_name = "root"; - const std::string kIsolatedFileSystemID = + IsolatedContext::ScopedFSHandle isolated_fs = IsolatedContext::GetInstance()->RegisterFileSystemForPath( - storage::kFileSystemTypeNativeLocal, - std::string(), + storage::kFileSystemTypeNativeLocal, std::string(), base::FilePath(DRIVE FPL("/test/isolated/root")), &isolated_file_system_name); + const std::string kIsolatedFileSystemID = isolated_fs.id(); // Register system external mount point. ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( - "system", - storage::kFileSystemTypeDrive, - FileSystemMountOption(), + "system", storage::kFileSystemTypeDrive, FileSystemMountOption(), base::FilePath(DRIVE FPL("/test/sys/")))); ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( - "ext", - storage::kFileSystemTypeNativeLocal, - FileSystemMountOption(), + "ext", storage::kFileSystemTypeNativeLocal, FileSystemMountOption(), base::FilePath(DRIVE FPL("/test/ext")))); // Register a system external mount point with the same name/id as the // registered isolated mount point. ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( - kIsolatedFileSystemID, - storage::kFileSystemTypeRestrictedNativeLocal, + kIsolatedFileSystemID, storage::kFileSystemTypeRestrictedNativeLocal, FileSystemMountOption(), base::FilePath(DRIVE FPL("/test/system/isolated")))); // Add a mount points with the same name as a system mount point to // FileSystemContext's external mount points. ASSERT_TRUE(external_mount_points->RegisterFileSystem( - "ext", - storage::kFileSystemTypeNativeLocal, - FileSystemMountOption(), + "ext", storage::kFileSystemTypeNativeLocal, FileSystemMountOption(), base::FilePath(DRIVE FPL("/test/local/ext/")))); const GURL kTestOrigin = GURL("http://chromium.org/"); @@ -252,14 +233,15 @@ const TestCase kTestCases[] = { // Following should not be handled by the url crackers: { - "pers_mount", "persistent", true /* is_valid */, - storage::kFileSystemTypePersistent, storage::kFileSystemTypePersistent, - FPL("pers_mount/root/file"), std::string() /* filesystem id */ + "pers_mount", "persistent", true /* is_valid */, + storage::kFileSystemTypePersistent, + storage::kFileSystemTypePersistent, FPL("pers_mount/root/file"), + std::string() /* filesystem id */ }, { - "temp_mount", "temporary", true /* is_valid */, - storage::kFileSystemTypeTemporary, storage::kFileSystemTypeTemporary, - FPL("temp_mount/root/file"), std::string() /* filesystem id */ + "temp_mount", "temporary", true /* is_valid */, + storage::kFileSystemTypeTemporary, storage::kFileSystemTypeTemporary, + FPL("temp_mount/root/file"), std::string() /* filesystem id */ }, // Should be cracked by isolated mount points: {kIsolatedFileSystemID, "isolated", true /* is_valid */, @@ -292,8 +274,8 @@ for (size_t i = 0; i < base::size(kTestCases); ++i) { const base::FilePath virtual_path = - base::FilePath::FromUTF8Unsafe( - kTestCases[i].root).Append(kVirtualPathNoRoot); + base::FilePath::FromUTF8Unsafe(kTestCases[i].root) + .Append(kVirtualPathNoRoot); GURL raw_url = CreateRawFileSystemURL(kTestCases[i].type_str, kTestCases[i].root); @@ -307,9 +289,7 @@ continue; ExpectFileSystemURLMatches( - cracked_url, - GURL(kTestOrigin), - kTestCases[i].expect_mount_type, + cracked_url, GURL(kTestOrigin), kTestCases[i].expect_mount_type, kTestCases[i].expect_type, base::FilePath(kTestCases[i].expect_path).NormalizePathSeparators(), virtual_path.NormalizePathSeparators(), @@ -338,26 +318,23 @@ // A request for an isolated mount point should NOT be served. std::string isolated_fs_name = "root"; - std::string isolated_fs_id = + IsolatedContext::ScopedFSHandle isolated_fs = IsolatedContext::GetInstance()->RegisterFileSystemForPath( - storage::kFileSystemTypeNativeLocal, - std::string(), - base::FilePath(DRIVE FPL("/test/isolated/root")), - &isolated_fs_name); - cracked_url = context->CrackURL( - CreateRawFileSystemURL("isolated", isolated_fs_id)); + storage::kFileSystemTypeNativeLocal, std::string(), + base::FilePath(DRIVE FPL("/test/isolated/root")), &isolated_fs_name); + std::string isolated_fs_id = isolated_fs.id(); + cracked_url = + context->CrackURL(CreateRawFileSystemURL("isolated", isolated_fs_id)); EXPECT_EQ(storage::kFileSystemTypeIsolated, cracked_url.mount_type()); EXPECT_FALSE(context->CanServeURLRequest(cracked_url)); // A request for an external mount point should be served. const std::string kExternalMountName = "ext_mount"; ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( - kExternalMountName, - storage::kFileSystemTypeDrive, - FileSystemMountOption(), - base::FilePath())); - cracked_url = context->CrackURL( - CreateRawFileSystemURL("external", kExternalMountName)); + kExternalMountName, storage::kFileSystemTypeDrive, + FileSystemMountOption(), base::FilePath())); + cracked_url = + context->CrackURL(CreateRawFileSystemURL("external", kExternalMountName)); EXPECT_EQ(storage::kFileSystemTypeExternal, cracked_url.mount_type()); EXPECT_TRUE(context->CanServeURLRequest(cracked_url));
diff --git a/storage/browser/fileapi/isolated_context.cc b/storage/browser/fileapi/isolated_context.cc index 6d930b8..acff276 100644 --- a/storage/browser/fileapi/isolated_context.cc +++ b/storage/browser/fileapi/isolated_context.cc
@@ -58,8 +58,8 @@ IsolatedContext::FileInfoSet::FileInfoSet() = default; IsolatedContext::FileInfoSet::~FileInfoSet() = default; -bool IsolatedContext::FileInfoSet::AddPath( - const base::FilePath& path, std::string* registered_name) { +bool IsolatedContext::FileInfoSet::AddPath(const base::FilePath& path, + std::string* registered_name) { // The given path should not contain any '..' and should be absolute. if (path.ReferencesParent() || !path.IsAbsolute()) return false; @@ -87,23 +87,64 @@ return true; } -bool IsolatedContext::FileInfoSet::AddPathWithName( - const base::FilePath& path, const std::string& name) { +bool IsolatedContext::FileInfoSet::AddPathWithName(const base::FilePath& path, + const std::string& name) { // The given path should not contain any '..' and should be absolute. if (path.ReferencesParent() || !path.IsAbsolute()) return false; - return fileset_.insert( - MountPointInfo(name, path.NormalizePathSeparators())).second; + return fileset_.insert(MountPointInfo(name, path.NormalizePathSeparators())) + .second; +} + +//-------------------------------------------------------------------------- + +IsolatedContext::ScopedFSHandle::ScopedFSHandle(std::string file_system_id) + : file_system_id_(std::move(file_system_id)) { + if (!file_system_id_.empty()) + IsolatedContext::GetInstance()->AddReference(file_system_id_); +} + +IsolatedContext::ScopedFSHandle::~ScopedFSHandle() { + if (!file_system_id_.empty()) + IsolatedContext::GetInstance()->RemoveReference(file_system_id_); +} + +IsolatedContext::ScopedFSHandle::ScopedFSHandle(const ScopedFSHandle& other) + : ScopedFSHandle(other.id()) {} + +IsolatedContext::ScopedFSHandle::ScopedFSHandle(ScopedFSHandle&& other) + : file_system_id_(std::move(other.file_system_id_)) { + // Moving from a string leaves it in a unspecified state, we need to make sure + // to leave it empty, so explicitly clear it. + other.file_system_id_.clear(); +} + +IsolatedContext::ScopedFSHandle& IsolatedContext::ScopedFSHandle::operator=( + const ScopedFSHandle& other) { + if (!file_system_id_.empty()) + IsolatedContext::GetInstance()->RemoveReference(file_system_id_); + file_system_id_ = other.id(); + if (!file_system_id_.empty()) + IsolatedContext::GetInstance()->AddReference(file_system_id_); + return *this; +} + +IsolatedContext::ScopedFSHandle& IsolatedContext::ScopedFSHandle::operator=( + ScopedFSHandle&& other) { + if (!file_system_id_.empty()) + IsolatedContext::GetInstance()->RemoveReference(file_system_id_); + file_system_id_ = std::move(other.file_system_id_); + // Moving from a string leaves it in a unspecified state, we need to make sure + // to leave it empty, so explicitly clear it. + other.file_system_id_.clear(); + return *this; } //-------------------------------------------------------------------------- class IsolatedContext::Instance { public: - enum PathType { - PLATFORM_PATH, - VIRTUAL_PATH - }; + enum PathType { PLATFORM_PATH, VIRTUAL_PATH }; // For a single-path isolated file system, which could be registered by // IsolatedContext::RegisterFileSystemForPath() or @@ -167,10 +208,7 @@ IsolatedContext::Instance::Instance(FileSystemType type, const std::set<MountPointInfo>& files) - : type_(type), - path_type_(PLATFORM_PATH), - files_(files), - ref_counts_(0) { + : type_(type), path_type_(PLATFORM_PATH), files_(files), ref_counts_(0) { DCHECK(!IsSinglePathIsolatedFileSystem(type_)); } @@ -224,14 +262,14 @@ return filesystem_id; } -std::string IsolatedContext::RegisterFileSystemForPath( +IsolatedContext::ScopedFSHandle IsolatedContext::RegisterFileSystemForPath( FileSystemType type, const std::string& filesystem_id, const base::FilePath& path_in, std::string* register_name) { base::FilePath path(path_in.NormalizePathSeparators()); if (path.ReferencesParent() || !path.IsAbsolute()) - return std::string(); + return ScopedFSHandle(); std::string name; if (register_name && !register_name->empty()) { name = *register_name; @@ -241,12 +279,16 @@ register_name->assign(name); } - base::AutoLock locker(lock_); - std::string new_id = GetNewFileSystemId(); - instance_map_[new_id] = std::make_unique<Instance>( - type, filesystem_id, MountPointInfo(name, path), Instance::PLATFORM_PATH); - path_to_id_map_[path].insert(new_id); - return new_id; + std::string new_id; + { + base::AutoLock locker(lock_); + new_id = GetNewFileSystemId(); + instance_map_[new_id] = std::make_unique<Instance>( + type, filesystem_id, MountPointInfo(name, path), + Instance::PLATFORM_PATH); + path_to_id_map_[path].insert(new_id); + } + return ScopedFSHandle(new_id); } std::string IsolatedContext::RegisterFileSystemForVirtualPath( @@ -276,8 +318,8 @@ return UnregisterFileSystem(filesystem_id); } -bool IsolatedContext::GetRegisteredPath( - const std::string& filesystem_id, base::FilePath* path) const { +bool IsolatedContext::GetRegisteredPath(const std::string& filesystem_id, + base::FilePath* path) const { DCHECK(path); base::AutoLock locker(lock_); auto found = instance_map_.find(filesystem_id); @@ -401,8 +443,7 @@ if (found == instance_map_.end() || found->second->type() != kFileSystemTypeDragged) return false; - files->assign(found->second->files().begin(), - found->second->files().end()); + files->assign(found->second->files().begin(), found->second->files().end()); return true; }
diff --git a/storage/browser/fileapi/isolated_context.h b/storage/browser/fileapi/isolated_context.h index 5ad38f6a7..b29feae 100644 --- a/storage/browser/fileapi/isolated_context.h +++ b/storage/browser/fileapi/isolated_context.h
@@ -61,6 +61,27 @@ std::set<MountPointInfo> fileset_; }; + // A handle to a Isolated File System, which properly refcounts the file + // system with the IsolatedContext when handles are created and destroyed. + class COMPONENT_EXPORT(STORAGE_BROWSER) ScopedFSHandle { + public: + ScopedFSHandle() = default; + // Like scoped_refptr, creating a new handle increases the refcount of the + // file system being referenced. + explicit ScopedFSHandle(std::string file_system_id); + ~ScopedFSHandle(); + ScopedFSHandle(const ScopedFSHandle& other); + ScopedFSHandle(ScopedFSHandle&& other); + ScopedFSHandle& operator=(const ScopedFSHandle& other); + ScopedFSHandle& operator=(ScopedFSHandle&& other); + + const std::string& id() const { return file_system_id_; } + bool is_valid() const { return !file_system_id_.empty(); } + + private: + std::string file_system_id_; + }; + // The instance is lazily created per browser process. static IsolatedContext* GetInstance(); @@ -93,15 +114,16 @@ std::string RegisterDraggedFileSystem(const FileInfoSet& files); // Registers a new isolated filesystem for a given |path| of filesystem - // |type| filesystem with |filesystem_id| and returns a new filesystem ID. + // |type| filesystem with |filesystem_id| and returns a handle for a new + // filesystem ID. // |path| must be an absolute path which has no parent references ('..'). // If |register_name| is non-null and has non-empty string the path is // registered as the given |register_name|, otherwise it is populated // with the name internally assigned to the path. - std::string RegisterFileSystemForPath(FileSystemType type, - const std::string& filesystem_id, - const base::FilePath& path, - std::string* register_name); + ScopedFSHandle RegisterFileSystemForPath(FileSystemType type, + const std::string& filesystem_id, + const base::FilePath& path, + std::string* register_name); // Registers a virtual filesystem. This is different from // RegisterFileSystemForPath because register_name is required, and
diff --git a/storage/browser/fileapi/isolated_context_unittest.cc b/storage/browser/fileapi/isolated_context_unittest.cc index b3c7354..6582748 100644 --- a/storage/browser/fileapi/isolated_context_unittest.cc +++ b/storage/browser/fileapi/isolated_context_unittest.cc
@@ -125,56 +125,59 @@ // Deref the current one and registering a new one. isolated_context()->RemoveReference(id_); - std::string id2 = isolated_context()->RegisterFileSystemForPath( - kFileSystemTypeNativeLocal, std::string(), - base::FilePath(DRIVE FPL("/foo")), nullptr); + IsolatedContext::ScopedFSHandle fs2 = + isolated_context()->RegisterFileSystemForPath( + kFileSystemTypeNativeLocal, std::string(), + base::FilePath(DRIVE FPL("/foo")), nullptr); // Make sure the GetDraggedFileInfo returns false for both ones. - ASSERT_FALSE(isolated_context()->GetDraggedFileInfo(id2, &toplevels)); + ASSERT_FALSE(isolated_context()->GetDraggedFileInfo(fs2.id(), &toplevels)); ASSERT_FALSE(isolated_context()->GetDraggedFileInfo(id_, &toplevels)); // Make sure the GetRegisteredPath returns true only for the new one. ASSERT_FALSE(isolated_context()->GetRegisteredPath(id_, &path)); - ASSERT_TRUE(isolated_context()->GetRegisteredPath(id2, &path)); + ASSERT_TRUE(isolated_context()->GetRegisteredPath(fs2.id(), &path)); // Try registering three more file systems for the same path as id2. - std::string id3 = isolated_context()->RegisterFileSystemForPath( - kFileSystemTypeNativeLocal, std::string(), path, nullptr); - std::string id4 = isolated_context()->RegisterFileSystemForPath( - kFileSystemTypeNativeLocal, std::string(), path, nullptr); - std::string id5 = isolated_context()->RegisterFileSystemForPath( - kFileSystemTypeNativeLocal, std::string(), path, nullptr); + IsolatedContext::ScopedFSHandle fs3 = + isolated_context()->RegisterFileSystemForPath( + kFileSystemTypeNativeLocal, std::string(), path, nullptr); + IsolatedContext::ScopedFSHandle fs4 = + isolated_context()->RegisterFileSystemForPath( + kFileSystemTypeNativeLocal, std::string(), path, nullptr); + IsolatedContext::ScopedFSHandle fs5 = + isolated_context()->RegisterFileSystemForPath( + kFileSystemTypeNativeLocal, std::string(), path, nullptr); // Remove file system for id4. - isolated_context()->AddReference(id4); - isolated_context()->RemoveReference(id4); + fs4 = IsolatedContext::ScopedFSHandle(); // Only id4 should become invalid now. - ASSERT_TRUE(isolated_context()->GetRegisteredPath(id2, &path)); - ASSERT_TRUE(isolated_context()->GetRegisteredPath(id3, &path)); - ASSERT_FALSE(isolated_context()->GetRegisteredPath(id4, &path)); - ASSERT_TRUE(isolated_context()->GetRegisteredPath(id5, &path)); + ASSERT_TRUE(isolated_context()->GetRegisteredPath(fs2.id(), &path)); + ASSERT_TRUE(isolated_context()->GetRegisteredPath(fs3.id(), &path)); + ASSERT_FALSE(isolated_context()->GetRegisteredPath(fs4.id(), &path)); + ASSERT_TRUE(isolated_context()->GetRegisteredPath(fs5.id(), &path)); // Revoke file system id5, after adding multiple references. - isolated_context()->AddReference(id5); - isolated_context()->AddReference(id5); - isolated_context()->AddReference(id5); - isolated_context()->RevokeFileSystem(id5); + isolated_context()->AddReference(fs5.id()); + isolated_context()->AddReference(fs5.id()); + isolated_context()->AddReference(fs5.id()); + isolated_context()->RevokeFileSystem(fs5.id()); // No matter how many references we add id5 must be invalid now. - ASSERT_TRUE(isolated_context()->GetRegisteredPath(id2, &path)); - ASSERT_TRUE(isolated_context()->GetRegisteredPath(id3, &path)); - ASSERT_FALSE(isolated_context()->GetRegisteredPath(id4, &path)); - ASSERT_FALSE(isolated_context()->GetRegisteredPath(id5, &path)); + ASSERT_TRUE(isolated_context()->GetRegisteredPath(fs2.id(), &path)); + ASSERT_TRUE(isolated_context()->GetRegisteredPath(fs3.id(), &path)); + ASSERT_FALSE(isolated_context()->GetRegisteredPath(fs4.id(), &path)); + ASSERT_FALSE(isolated_context()->GetRegisteredPath(fs5.id(), &path)); // Revoke the file systems by path. isolated_context()->RevokeFileSystemByPath(path); // Now all the file systems associated to the path must be invalid. - ASSERT_FALSE(isolated_context()->GetRegisteredPath(id2, &path)); - ASSERT_FALSE(isolated_context()->GetRegisteredPath(id3, &path)); - ASSERT_FALSE(isolated_context()->GetRegisteredPath(id4, &path)); - ASSERT_FALSE(isolated_context()->GetRegisteredPath(id5, &path)); + ASSERT_FALSE(isolated_context()->GetRegisteredPath(fs2.id(), &path)); + ASSERT_FALSE(isolated_context()->GetRegisteredPath(fs3.id(), &path)); + ASSERT_FALSE(isolated_context()->GetRegisteredPath(fs4.id(), &path)); + ASSERT_FALSE(isolated_context()->GetRegisteredPath(fs5.id(), &path)); } TEST_F(IsolatedContextTest, CrackWithRelativePaths) {
diff --git a/storage/browser/fileapi/transient_file_util_unittest.cc b/storage/browser/fileapi/transient_file_util_unittest.cc index 0567b32..4994ec5c 100644 --- a/storage/browser/fileapi/transient_file_util_unittest.cc +++ b/storage/browser/fileapi/transient_file_util_unittest.cc
@@ -42,19 +42,19 @@ void CreateAndRegisterTemporaryFile( FileSystemURL* file_url, - base::FilePath* file_path) { + base::FilePath* file_path, + storage::IsolatedContext::ScopedFSHandle* filesystem) { EXPECT_TRUE(base::CreateTemporaryFileInDir(data_dir_.GetPath(), file_path)); storage::IsolatedContext* isolated_context = storage::IsolatedContext::GetInstance(); std::string name = "tmp"; - std::string fsid = isolated_context->RegisterFileSystemForPath( - storage::kFileSystemTypeForTransientFile, - std::string(), - *file_path, + *filesystem = isolated_context->RegisterFileSystemForPath( + storage::kFileSystemTypeForTransientFile, std::string(), *file_path, &name); - ASSERT_TRUE(!fsid.empty()); - base::FilePath virtual_path = isolated_context->CreateVirtualRootPath( - fsid).AppendASCII(name); + ASSERT_TRUE(filesystem->is_valid()); + base::FilePath virtual_path = + isolated_context->CreateVirtualRootPath(filesystem->id()) + .AppendASCII(name); *file_url = file_system_context_->CreateCrackedFileSystemURL( GURL("http://foo"), storage::kFileSystemTypeIsolated, virtual_path); } @@ -80,8 +80,9 @@ TEST_F(TransientFileUtilTest, TransientFile) { FileSystemURL temp_url; base::FilePath temp_path; + storage::IsolatedContext::ScopedFSHandle filesystem; - CreateAndRegisterTemporaryFile(&temp_url, &temp_path); + CreateAndRegisterTemporaryFile(&temp_url, &temp_path, &filesystem); base::File::Error error; base::File::Info file_info; @@ -103,8 +104,8 @@ // The file should be still there. ASSERT_TRUE(base::PathExists(temp_path)); ASSERT_EQ(base::File::FILE_OK, - file_util()->GetFileInfo(NewOperationContext().get(), - temp_url, &file_info, &path)); + file_util()->GetFileInfo(NewOperationContext().get(), temp_url, + &file_info, &path)); ASSERT_EQ(temp_path, path); ASSERT_FALSE(file_info.is_directory); } @@ -115,8 +116,8 @@ // Now the temporary file and the transient filesystem must be gone too. ASSERT_FALSE(base::PathExists(temp_path)); ASSERT_EQ(base::File::FILE_ERROR_NOT_FOUND, - file_util()->GetFileInfo(NewOperationContext().get(), - temp_url, &file_info, &path)); + file_util()->GetFileInfo(NewOperationContext().get(), temp_url, + &file_info, &path)); } } // namespace content
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json index bf56458..3c0a9b8 100644 --- a/testing/buildbot/chromium.clang.json +++ b/testing/buildbot/chromium.clang.json
@@ -7216,14 +7216,46 @@ "gtest_tests": [ { "args": [ - "--tool=asan" + "--tool=asan", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" ], "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "base_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, "swarming": { - "can_use_on_swarming_builders": false + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_os_type": "userdebug", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] }, "test": "base_unittests" }
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 7f7326f7..d1ed8b4 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -776,7 +776,16 @@ 'gtest_tests': 'chromium_android_asan_gtests', 'junit_tests': 'chromium_android_asan_junit_tests', }, - 'use_swarming': False, + 'swarming': { + 'dimension_sets': [ + { + 'device_os': 'MMB29Q', + 'device_type': 'bullhead', + 'os': 'Android', + }, + ], + }, + 'os_type': 'android', }, 'ToTAndroidCFI': { 'swarming': {
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/third_party/blink/renderer/core/display_lock/display_lock_context.cc index 03d86ba6..2aede93 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_context.cc +++ b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -829,7 +829,7 @@ // forcing an update from the ancestor locks seems inefficient. For now, we // just optimistically assume that we have all of the right containment in // place. See crbug.com/926276 for more information. - if (IsElementDirtyForStyleRecalc()) + if (element_->NeedsStyleRecalc()) return true; // If we have a layout object, check that since it's a more authoritative
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index 91bd8ed..0b067e0 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -175,23 +175,28 @@ DisplayLockStyleScope(DisplayLockContext* context) : context_(context), should_update_self_(!context || - context->ShouldStyle(DisplayLockContext::kSelf)), - should_update_children_( - !context || context->ShouldStyle(DisplayLockContext::kChildren)) {} + context->ShouldStyle(DisplayLockContext::kSelf)) {} + ~DisplayLockStyleScope() { if (!context_) return; if (did_update_children_) context_->DidStyle(DisplayLockContext::kChildren); - // There is no other condition to block us form updating self, so if we - // "should" update, then we "did" update. - if (should_update_self_) - context_->DidStyle(DisplayLockContext::kSelf); } bool ShouldUpdateSelfStyle() const { return should_update_self_; } - bool ShouldUpdateChildStyle() const { return should_update_children_; } + bool ShouldUpdateChildStyle() const { + // We can't calculate this on construction time, because the element might + // get unlocked after self-style calculation due to lack of containment, + // which might change the value of ShouldStyle(children). + return !context_ || context_->ShouldStyle(DisplayLockContext::kChildren); + } void DidUpdateChildStyle() { did_update_children_ = true; } + void DidUpdateSelfStyle() { + DCHECK(should_update_self_); + if (context_) + context_->DidStyle(DisplayLockContext::kSelf); + } void NotifyUpdateWasBlocked(DisplayLockContext::StyleType style) { DCHECK(!ShouldUpdateChildStyle()); @@ -201,7 +206,6 @@ private: UntracedMember<DisplayLockContext> context_; const bool should_update_self_; - const bool should_update_children_; bool did_update_children_ = false; }; @@ -2357,6 +2361,9 @@ child_change = child_change.ForceRecalcDescendants(); ClearNeedsStyleRecalc(); } + // We're done with self-style, notify so that containment checks etc for + // display locking can happen.. + display_lock_style_scope.DidUpdateSelfStyle(); if (child_change.TraversePseudoElements(*this)) { UpdatePseudoElement(kPseudoIdBackdrop, child_change); @@ -2374,7 +2381,6 @@ } else { RecalcDescendantStyles(child_change); } - display_lock_style_scope.DidUpdateChildStyle(); } if (child_change.TraversePseudoElements(*this)) { @@ -2389,6 +2395,8 @@ if (should_update_child_style) { ClearChildNeedsStyleRecalc(); + // We've updated all the children that needs an update (might be 0). + display_lock_style_scope.DidUpdateChildStyle(); } else if (child_change.RecalcChildren()) { // If we should've calculated the style for children but was blocked, // notify so that we'd come back.
diff --git a/third_party/blink/renderer/core/editing/selection_modifier_line.cc b/third_party/blink/renderer/core/editing/selection_modifier_line.cc index 80bae8c..a15df39 100644 --- a/third_party/blink/renderer/core/editing/selection_modifier_line.cc +++ b/third_party/blink/renderer/core/editing/selection_modifier_line.cc
@@ -34,22 +34,210 @@ #include "third_party/blink/renderer/core/editing/inline_box_position.h" #include "third_party/blink/renderer/core/editing/visible_position.h" #include "third_party/blink/renderer/core/editing/visible_units.h" +#include "third_party/blink/renderer/core/layout/api/line_layout_api_shim.h" #include "third_party/blink/renderer/core/layout/api/line_layout_block_flow.h" #include "third_party/blink/renderer/core/layout/line/root_inline_box.h" +#include "third_party/blink/renderer/core/layout/ng/inline/ng_line_utils.h" +#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h" +#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h" +#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h" namespace blink { namespace { -const RootInlineBox* ComputeContainingLineBox(const VisiblePosition& position) { +// Abstracts similarities between RootInlineBox and NGPhysicalLineBoxFragment +class AbstractLineBox { + STACK_ALLOCATED(); + + public: + AbstractLineBox() = default; + + static AbstractLineBox CreateFor(const VisiblePosition&); + + bool IsNull() const { return type_ == Type::kNull; } + + bool CanBeCaretContainer() const { + DCHECK(!IsNull()); + // We want to skip zero height boxes. + // This could happen in case it is a TrailingFloatsRootInlineBox. + if (IsOldLayout()) { + return GetRootInlineBox().LogicalHeight() && + GetRootInlineBox().FirstLeafChild(); + } + if (GetLineBoxFragment().IsEmptyLineBox()) + return false; + const PhysicalSize physical_size = GetLineBoxFragment().Size(); + const LogicalSize logical_size = physical_size.ConvertToLogical( + GetLineBoxFragment().Style().GetWritingMode()); + if (!logical_size.block_size) + return false; + // Use |ClosestLeafChildForPoint| to check if there's any leaf child. + return GetLineBoxFragment().ClosestLeafChildForPoint(PhysicalOffset(), + false); + } + + AbstractLineBox PreviousLine() const { + DCHECK(!IsNull()); + if (IsOldLayout()) { + const RootInlineBox* previous_root = GetRootInlineBox().PrevRootBox(); + return previous_root ? AbstractLineBox(*previous_root) + : AbstractLineBox(); + } + const auto children = ng_box_fragment_->Children(); + for (wtf_size_t i = ng_child_index_; i;) { + --i; + if (!children[i]->IsLineBox()) + continue; + return AbstractLineBox(*ng_box_fragment_, i); + } + return AbstractLineBox(); + } + + AbstractLineBox NextLine() const { + DCHECK(!IsNull()); + if (IsOldLayout()) { + const RootInlineBox* next_root = GetRootInlineBox().NextRootBox(); + return next_root ? AbstractLineBox(*next_root) : AbstractLineBox(); + } + const auto children = ng_box_fragment_->Children(); + for (wtf_size_t i = ng_child_index_ + 1; i < children.size(); ++i) { + if (!children[i]->IsLineBox()) + continue; + return AbstractLineBox(*ng_box_fragment_, i); + } + return AbstractLineBox(); + } + + LayoutPoint AbsoluteLineDirectionPointToLocalPointInBlock( + LayoutUnit line_direction_point) { + DCHECK(!IsNull()); + const LayoutBlockFlow& containing_block = GetBlock(); + FloatPoint absolute_block_point = + containing_block.LocalToAbsolute(FloatPoint()); + if (containing_block.HasOverflowClip()) { + absolute_block_point -= + FloatSize(containing_block.ScrolledContentOffset()); + } + + if (containing_block.Style()->IsHorizontalWritingMode()) { + return LayoutPoint( + LayoutUnit(line_direction_point - absolute_block_point.X()), + BlockDirectionPointInLine()); + } + + return LayoutPoint( + BlockDirectionPointInLine(), + LayoutUnit(line_direction_point - absolute_block_point.Y())); + } + + const LayoutObject* ClosestLeafChildForPoint( + const LayoutPoint& point, + bool only_editable_leaves) const { + DCHECK(!IsNull()); + if (IsOldLayout()) { + return GetRootInlineBox().ClosestLeafChildForPoint(point, + only_editable_leaves); + } + const LayoutSize unit_square(1, 1); + const PhysicalRect physical_rect = + GetBlock().FlipForWritingMode(LayoutRect(point, unit_square)); + const PhysicalOffset physical_point = physical_rect.offset; + const PhysicalOffset local_physical_point = + physical_point - ng_box_fragment_->Children()[ng_child_index_].offset; + return GetLineBoxFragment().ClosestLeafChildForPoint(local_physical_point, + only_editable_leaves); + } + + private: + explicit AbstractLineBox(const RootInlineBox& root_inline_box) + : root_inline_box_(&root_inline_box), type_(Type::kOldLayout) {} + + AbstractLineBox(const NGPhysicalBoxFragment& box_fragment, + wtf_size_t child_index) + : ng_box_fragment_(&box_fragment), + ng_child_index_(child_index), + type_(Type::kLayoutNG) { + DCHECK_LT(child_index, box_fragment.Children().size()); + DCHECK(box_fragment.Children()[child_index]->IsLineBox()); + } + + const LayoutBlockFlow& GetBlock() const { + DCHECK(!IsNull()); + if (IsOldLayout()) { + return *To<LayoutBlockFlow>( + LineLayoutAPIShim::LayoutObjectFrom(GetRootInlineBox().Block())); + } + DCHECK(ng_box_fragment_->GetLayoutObject()); + return *To<LayoutBlockFlow>(ng_box_fragment_->GetLayoutObject()); + } + + LayoutUnit BlockDirectionPointInLine() const { + DCHECK(!IsNull()); + if (IsOldLayout()) + return GetRootInlineBox().BlockDirectionPointInLine(); + const PhysicalOffset physical_offset = + ng_box_fragment_->Children()[ng_child_index_].offset; + const LogicalOffset logical_offset = physical_offset.ConvertToLogical( + ng_box_fragment_->Style().GetWritingMode(), + GetLineBoxFragment().BaseDirection(), ng_box_fragment_->Size(), + GetLineBoxFragment().Size()); + return logical_offset.block_offset; + } + + bool IsOldLayout() const { return type_ == Type::kOldLayout; } + + bool IsLayoutNG() const { return type_ == Type::kLayoutNG; } + + const RootInlineBox& GetRootInlineBox() const { + DCHECK(IsOldLayout()); + return *root_inline_box_; + } + + const NGPhysicalLineBoxFragment& GetLineBoxFragment() const { + DCHECK(IsLayoutNG()); + return To<NGPhysicalLineBoxFragment>( + *ng_box_fragment_->Children()[ng_child_index_]); + } + + enum class Type { kNull, kOldLayout, kLayoutNG }; + + const RootInlineBox* root_inline_box_ = nullptr; + const NGPhysicalBoxFragment* ng_box_fragment_ = nullptr; + wtf_size_t ng_child_index_ = 0u; + Type type_ = Type::kNull; +}; + +// static +AbstractLineBox AbstractLineBox::CreateFor(const VisiblePosition& position) { if (position.IsNull() || !position.DeepEquivalent().AnchorNode()->GetLayoutObject()) { - return nullptr; + return AbstractLineBox(); } - const InlineBox* box = ComputeInlineBoxPosition(position).inline_box; + + const PositionWithAffinity adjusted = ComputeInlineAdjustedPosition(position); + if (adjusted.IsNull()) + return AbstractLineBox(); + + if (const NGPaintFragment* line_paint_fragment = + NGContainingLineBoxOf(adjusted)) { + const NGPhysicalBoxFragment& box_fragment = To<NGPhysicalBoxFragment>( + line_paint_fragment->Parent()->PhysicalFragment()); + const NGPhysicalFragment& line_box_fragment = + line_paint_fragment->PhysicalFragment(); + for (wtf_size_t i = 0; i < box_fragment.Children().size(); ++i) { + if (box_fragment.Children()[i].get() == &line_box_fragment) + return AbstractLineBox(box_fragment, i); + } + NOTREACHED(); + return AbstractLineBox(); + } + + const InlineBox* box = + ComputeInlineBoxPositionForInlineAdjustedPosition(adjusted).inline_box; if (!box) - return nullptr; - return &box->Root(); + return AbstractLineBox(); + return AbstractLineBox(box->Root()); } ContainerNode* HighestEditableRootOfNode(const Node& node) { @@ -125,27 +313,6 @@ return nullptr; } -LayoutPoint AbsoluteLineDirectionPointToLocalPointInBlock( - const RootInlineBox* root, - LayoutUnit line_direction_point) { - DCHECK(root); - LineLayoutBlockFlow containing_block = root->Block(); - FloatPoint absolute_block_point = - containing_block.LocalToAbsolute(FloatPoint()); - if (containing_block.HasOverflowClip()) - absolute_block_point -= FloatSize(containing_block.ScrolledContentOffset()); - - if (containing_block.IsHorizontalWritingMode()) { - return LayoutPoint( - LayoutUnit(line_direction_point - absolute_block_point.X()), - root->BlockDirectionPointInLine()); - } - - return LayoutPoint( - root->BlockDirectionPointInLine(), - LayoutUnit(line_direction_point - absolute_block_point.Y())); -} - bool InSameLine(const Node& node, const VisiblePosition& visible_position) { if (!node.GetLayoutObject()) return true; @@ -234,22 +401,20 @@ if (!layout_object) return VisiblePosition(); - const RootInlineBox* root = ComputeContainingLineBox(visible_position); - if (root) { - root = root->PrevRootBox(); - // We want to skip zero height boxes. - // This could happen in case it is a TrailingFloatsRootInlineBox. - if (!root || !root->LogicalHeight() || !root->FirstLeafChild()) - root = nullptr; + AbstractLineBox line = AbstractLineBox::CreateFor(visible_position); + if (!line.IsNull()) { + line = line.PreviousLine(); + if (line.IsNull() || !line.CanBeCaretContainer()) + line = AbstractLineBox(); } - if (!root) { + if (line.IsNull()) { Position position = PreviousRootInlineBoxCandidatePosition(node, visible_position); if (position.IsNotNull()) { const VisiblePosition candidate = CreateVisiblePosition(position); - root = ComputeContainingLineBox(candidate); - if (!root) { + line = AbstractLineBox::CreateFor(candidate); + if (line.IsNull()) { // TODO(editing-dev): Investigate if this is correct for null // |candidate|. return candidate; @@ -257,17 +422,20 @@ } } - if (root) { + if (!line.IsNull()) { // FIXME: Can be wrong for multi-column layout and with transforms. - LayoutPoint point_in_line = AbsoluteLineDirectionPointToLocalPointInBlock( - root, line_direction_point); + LayoutPoint point_in_line = + line.AbsoluteLineDirectionPointToLocalPointInBlock( + line_direction_point); const LayoutObject* closest_leaf_child = - root->ClosestLeafChildForPoint(point_in_line, IsEditablePosition(p)); - const Node* node = closest_leaf_child->GetNode(); - if (node && EditingIgnoresContent(*node)) - return VisiblePosition::InParentBeforeNode(*node); - return CreateVisiblePosition( - closest_leaf_child->PositionForPoint(point_in_line)); + line.ClosestLeafChildForPoint(point_in_line, IsEditablePosition(p)); + if (closest_leaf_child) { + const Node* node = closest_leaf_child->GetNode(); + if (node && EditingIgnoresContent(*node)) + return VisiblePosition::InParentBeforeNode(*node); + return CreateVisiblePosition( + closest_leaf_child->PositionForPoint(point_in_line)); + } } // Could not find a previous line. This means we must already be on the first @@ -299,16 +467,14 @@ if (!layout_object) return VisiblePosition(); - const RootInlineBox* root = ComputeContainingLineBox(visible_position); - if (root) { - root = root->NextRootBox(); - // We want to skip zero height boxes. - // This could happen in case it is a TrailingFloatsRootInlineBox. - if (!root || !root->LogicalHeight() || !root->FirstLeafChild()) - root = nullptr; + AbstractLineBox line = AbstractLineBox::CreateFor(visible_position); + if (!line.IsNull()) { + line = line.NextLine(); + if (line.IsNull() || !line.CanBeCaretContainer()) + line = AbstractLineBox(); } - if (!root) { + if (line.IsNull()) { // FIXME: We need do the same in previousLinePosition. Node* child = NodeTraversal::ChildAt(*node, p.ComputeEditingOffset()); Node* search_start_node = @@ -317,8 +483,8 @@ NextRootInlineBoxCandidatePosition(search_start_node, visible_position); if (position.IsNotNull()) { const VisiblePosition candidate = CreateVisiblePosition(position); - root = ComputeContainingLineBox(candidate); - if (!root) { + line = AbstractLineBox::CreateFor(candidate); + if (line.IsNull()) { // TODO(editing-dev): Investigate if this is correct for null // |candidate|. return candidate; @@ -326,17 +492,20 @@ } } - if (root) { + if (!line.IsNull()) { // FIXME: Can be wrong for multi-column layout and with transforms. - LayoutPoint point_in_line = AbsoluteLineDirectionPointToLocalPointInBlock( - root, line_direction_point); + LayoutPoint point_in_line = + line.AbsoluteLineDirectionPointToLocalPointInBlock( + line_direction_point); const LayoutObject* closest_leaf_child = - root->ClosestLeafChildForPoint(point_in_line, IsEditablePosition(p)); - const Node* node = closest_leaf_child->GetNode(); - if (node && EditingIgnoresContent(*node)) - return VisiblePosition::InParentBeforeNode(*node); - return CreateVisiblePosition( - closest_leaf_child->PositionForPoint(point_in_line)); + line.ClosestLeafChildForPoint(point_in_line, IsEditablePosition(p)); + if (closest_leaf_child) { + const Node* node = closest_leaf_child->GetNode(); + if (node && EditingIgnoresContent(*node)) + return VisiblePosition::InParentBeforeNode(*node); + return CreateVisiblePosition( + closest_leaf_child->PositionForPoint(point_in_line)); + } } // Could not find a next line. This means we must already be on the last line.
diff --git a/third_party/blink/renderer/core/inspector/browser_protocol.pdl b/third_party/blink/renderer/core/inspector/browser_protocol.pdl index 9de341fc..77b8f805 100644 --- a/third_party/blink/renderer/core/inspector/browser_protocol.pdl +++ b/third_party/blink/renderer/core/inspector/browser_protocol.pdl
@@ -6112,6 +6112,10 @@ string vendorString # String description of the GPU device, if the PCI ID is not available. string deviceString + # String description of the GPU driver vendor. + string driverVendor + # String description of the GPU driver version. + string driverVersion # Provides information about the GPU(s) on the system. type GPUInfo extends object
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.cc b/third_party/blink/renderer/core/layout/layout_block_flow.cc index b5a31fbc..1cb5211d 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow.cc +++ b/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -4597,7 +4597,7 @@ void LayoutBlockFlow::RecalcInlineChildrenVisualOverflow() { DCHECK(ChildrenInline()); - if (NGPaintFragment* paint_fragment = PaintFragment()) { + if (const NGPaintFragment* paint_fragment = PaintFragment()) { paint_fragment->RecalcInlineChildrenInkOverflow(); return; }
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow_line.cc b/third_party/blink/renderer/core/layout/layout_block_flow_line.cc index 57167c8f..e9a2365 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow_line.cc +++ b/third_party/blink/renderer/core/layout/layout_block_flow_line.cc
@@ -2687,7 +2687,7 @@ DCHECK(ChildrenInline()); if (RootInlineBox* first_root_box = FirstRootBox()) first_root_box->SetShouldDoFullPaintInvalidationRecursively(); - else if (NGPaintFragment* paint_fragment = PaintFragment()) + else if (const NGPaintFragment* paint_fragment = PaintFragment()) paint_fragment->SetShouldDoFullPaintInvalidationForFirstLine(); }
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h index c800e7fac..7577d63 100644 --- a/third_party/blink/renderer/core/layout/layout_object.h +++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -1330,7 +1330,7 @@ // Returns the associated |NGPaintFragment|. When this is not a |nullptr|, // this is the root of an inline formatting context, laid out by LayoutNG. - virtual NGPaintFragment* PaintFragment() const { return nullptr; } + virtual const NGPaintFragment* PaintFragment() const { return nullptr; } // Paint/Physical fragments are not in sync with LayoutObject tree until it is // laid out. For inline, it needs to check if the containing block is
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_dirty_lines.h b/third_party/blink/renderer/core/layout/ng/inline/ng_dirty_lines.h index 0bd6100..5e97423c 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_dirty_lines.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_dirty_lines.h
@@ -18,7 +18,7 @@ STACK_ALLOCATED(); public: - explicit NGDirtyLines(NGPaintFragment* block_fragment) + explicit NGDirtyLines(const NGPaintFragment* block_fragment) : block_fragment_(block_fragment) { DCHECK(block_fragment_); } @@ -82,7 +82,7 @@ // is |nullptr|, the first line box is marked as dirty. void MarkLastFragment(); - NGPaintFragment* block_fragment_; + const NGPaintFragment* block_fragment_; NGPaintFragment* last_fragment_ = nullptr; };
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc index cc3c4d4..e7462d8 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
@@ -349,7 +349,7 @@ } if (RuntimeEnabledFeatures::LayoutNGLineCacheEnabled()) { - if (NGPaintFragment* fragment = block_flow->PaintFragment()) { + if (const NGPaintFragment* fragment = block_flow->PaintFragment()) { NGDirtyLines dirty_lines(fragment); PrepareLayout(std::move(previous_data), &dirty_lines); return; @@ -442,6 +442,10 @@ LayoutBlockFlow* layout_block_flow) { DCHECK(!layout_block_flow->GetDocument().NeedsLayoutTreeUpdate()); + // TODO(crbug.com/962129): Fix the root cause of the missing layout, and turn + // this into a DCHECK. + CHECK(!layout_block_flow->NeedsLayout()) << layout_block_flow; + // If |layout_block_flow| is LayoutNG, compute from |NGInlineNode|. if (layout_block_flow->IsLayoutNGMixin()) { NGInlineNode node(layout_block_flow); @@ -996,7 +1000,7 @@ if (constraint_space.HasBlockFragmentation()) return nullptr; - NGPaintFragment* paint_fragment = block_flow->PaintFragment(); + const NGPaintFragment* paint_fragment = block_flow->PaintFragment(); if (!paint_fragment) return nullptr; @@ -1015,7 +1019,7 @@ // |DirtyLinesFromChangedChild()|, but insertions and style changes are not // marked yet. bool NGInlineNode::MarkLineBoxesDirty(LayoutBlockFlow* block_flow, - NGPaintFragment* paint_fragment) { + const NGPaintFragment* paint_fragment) { DCHECK(RuntimeEnabledFeatures::LayoutNGLineCacheEnabled()); NGDirtyLines dirty_lines(paint_fragment); if (block_flow->NeedsCollectInlines()) {
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h index 25ab690b..a3bcb07a 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h
@@ -126,7 +126,7 @@ void ShapeTextForFirstLineIfNeeded(NGInlineNodeData*); void AssociateItemsWithInlines(NGInlineNodeData*); - bool MarkLineBoxesDirty(LayoutBlockFlow*, NGPaintFragment*); + bool MarkLineBoxesDirty(LayoutBlockFlow*, const NGPaintFragment*); NGInlineNodeData* MutableData() { return To<LayoutBlockFlow>(box_)->GetNGInlineNodeData();
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc index 8da9010..249da59 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc
@@ -4,7 +4,9 @@ #include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h" +#include "third_party/blink/renderer/core/editing/editing_utilities.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h" +#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.h" #include "third_party/blink/renderer/core/layout/ng/ng_fragment.h" #include "third_party/blink/renderer/core/layout/ng/ng_relative_utils.h" @@ -22,6 +24,18 @@ sizeof(SameSizeAsNGPhysicalLineBoxFragment), "NGPhysicalLineBoxFragment should stay small"); +bool IsInlineLeaf(const NGPhysicalFragment& fragment) { + if (fragment.IsText()) + return true; + return fragment.IsBox() && fragment.IsAtomicInline(); +} + +bool IsEditableFragment(const NGPhysicalFragment& fragment) { + if (!fragment.GetNode()) + return false; + return HasEditableStyle(*fragment.GetNode()); +} + } // namespace scoped_refptr<const NGPhysicalLineBoxFragment> @@ -149,4 +163,47 @@ BaseDirection(), Size(), pixel_size); } +const LayoutObject* NGPhysicalLineBoxFragment::ClosestLeafChildForPoint( + const PhysicalOffset& point, + bool only_editable_leaves) const { + const PhysicalSize unit_square(LayoutUnit(1), LayoutUnit(1)); + const LogicalOffset logical_point = point.ConvertToLogical( + Style().GetWritingMode(), BaseDirection(), Size(), unit_square); + const LayoutUnit inline_offset = logical_point.inline_offset; + const NGPhysicalFragment* closest_leaf_child = nullptr; + LayoutUnit closest_leaf_distance; + for (const auto& descendant : + NGInlineFragmentTraversal::DescendantsOf(*this)) { + const NGPhysicalFragment& fragment = *descendant.fragment; + if (!fragment.GetLayoutObject()) + continue; + if (!IsInlineLeaf(fragment) || fragment.IsListMarker()) + continue; + if (only_editable_leaves && !IsEditableFragment(fragment)) + continue; + + const LogicalSize fragment_logical_size = + fragment.Size().ConvertToLogical(Style().GetWritingMode()); + const LogicalOffset fragment_logical_offset = + descendant.offset_to_container_box.ConvertToLogical( + Style().GetWritingMode(), BaseDirection(), Size(), fragment.Size()); + const LayoutUnit inline_min = fragment_logical_offset.inline_offset; + const LayoutUnit inline_max = fragment_logical_offset.inline_offset + + fragment_logical_size.inline_size; + if (inline_offset >= inline_min && inline_offset < inline_max) + return fragment.GetLayoutObject(); + + const LayoutUnit distance = + inline_offset < inline_min ? inline_min - inline_offset + : inline_offset - inline_max + LayoutUnit(1); + if (!closest_leaf_child || distance < closest_leaf_distance) { + closest_leaf_child = &fragment; + closest_leaf_distance = distance; + } + } + if (!closest_leaf_child) + return nullptr; + return closest_leaf_child->GetLayoutObject(); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h b/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h index a919365..d12c481 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h
@@ -69,6 +69,9 @@ const NGPhysicalFragment* FirstLogicalLeaf() const; const NGPhysicalFragment* LastLogicalLeaf() const; + const LayoutObject* ClosestLeafChildForPoint(const PhysicalOffset&, + bool only_editable_leaves) const; + // Returns a point at the visual start/end of the line. // Encapsulates the handling of text direction and writing mode. PhysicalOffset LineStartPoint() const;
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h index 9799e2b..7f45d582 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h +++ b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h
@@ -50,7 +50,7 @@ PositionWithAffinity PositionForPoint(const LayoutPoint&) const override; - NGPaintFragment* PaintFragment() const final { + const NGPaintFragment* PaintFragment() const final { // TODO(layout-dev) crbug.com/963103 // Safer option here is to return nullptr only if // Lifecycle > DocumentLifecycle::kAfterPerformLayout, but this breaks
diff --git a/third_party/blink/renderer/core/layout/scroll_anchor.cc b/third_party/blink/renderer/core/layout/scroll_anchor.cc index 9bea1dca..430cb50 100644 --- a/third_party/blink/renderer/core/layout/scroll_anchor.cc +++ b/third_party/blink/renderer/core/layout/scroll_anchor.cc
@@ -98,6 +98,9 @@ } } else if (layout_object->IsText()) { const auto* text = ToLayoutText(layout_object); + // TODO(kojii): |PhysicalLinesBoundingBox()| cannot compute, and thus + // returns (0, 0) when changes are made that |DeleteLineBoxes()| or clear + // |SetPaintFragment()|, e.g., |SplitFlow()|. crbug.com/965352 PhysicalRect bounds = text->PhysicalLinesBoundingBox(); local_bounds.Unite(text->FlipForWritingMode(bounds)); } else {
diff --git a/third_party/blink/renderer/core/paint/block_flow_paint_invalidator.cc b/third_party/blink/renderer/core/paint/block_flow_paint_invalidator.cc index 7d02121..68051369 100644 --- a/third_party/blink/renderer/core/paint/block_flow_paint_invalidator.cc +++ b/third_party/blink/renderer/core/paint/block_flow_paint_invalidator.cc
@@ -45,7 +45,7 @@ ObjectPaintInvalidator object_paint_invalidator(block_flow_); object_paint_invalidator.InvalidateDisplayItemClient(block_flow_, reason); - NGPaintFragment* paint_fragment = block_flow_.PaintFragment(); + const NGPaintFragment* paint_fragment = block_flow_.PaintFragment(); if (paint_fragment) { object_paint_invalidator.InvalidateDisplayItemClient(*paint_fragment, reason);
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc index eb6c960..1ad6b03 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
@@ -429,11 +429,11 @@ add_result.stored_value->value = this; } -NGPaintFragment* NGPaintFragment::GetForInlineContainer( +const NGPaintFragment* NGPaintFragment::GetForInlineContainer( const LayoutObject* layout_object) { DCHECK(layout_object && layout_object->IsInline()); if (LayoutBlockFlow* block_flow = layout_object->ContainingNGBlockFlow()) { - if (NGPaintFragment* fragment = block_flow->PaintFragment()) + if (const NGPaintFragment* fragment = block_flow->PaintFragment()) return fragment; // TODO(kojii): IsLayoutFlowThread should probably be done in @@ -558,12 +558,12 @@ return rect; } -void NGPaintFragment::RecalcInlineChildrenInkOverflow() { +void NGPaintFragment::RecalcInlineChildrenInkOverflow() const { DCHECK(GetLayoutObject()->ChildrenInline()); RecalcContentsInkOverflow(); } -PhysicalRect NGPaintFragment::RecalcContentsInkOverflow() { +PhysicalRect NGPaintFragment::RecalcContentsInkOverflow() const { PhysicalRect contents_rect; for (NGPaintFragment* child : Children()) { const NGPhysicalFragment& child_fragment = child->PhysicalFragment(); @@ -769,7 +769,7 @@ // The |layout_object| is inserted into an empty block. // Mark the first line box dirty. - if (NGPaintFragment* paint_fragment = parent.PaintFragment()) { + if (const NGPaintFragment* paint_fragment = parent.PaintFragment()) { if (NGPaintFragment* first_line = paint_fragment->FirstLineBox()) { first_line->is_dirty_inline_ = true; return; @@ -825,7 +825,7 @@ child->SetShouldDoFullPaintInvalidationRecursively(); } -void NGPaintFragment::SetShouldDoFullPaintInvalidationForFirstLine() { +void NGPaintFragment::SetShouldDoFullPaintInvalidationForFirstLine() const { DCHECK(PhysicalFragment().IsBox() && GetLayoutObject() && GetLayoutObject()->IsLayoutBlockFlow());
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h index d71b3d1..52831710 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h +++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
@@ -157,7 +157,7 @@ // overflow of this object (e.g. when not clipped,) in the local coordinate. PhysicalRect InkOverflow() const; - void RecalcInlineChildrenInkOverflow(); + void RecalcInlineChildrenInkOverflow() const; void AddSelfOutlineRects(Vector<PhysicalRect>*, const PhysicalOffset& offset, @@ -185,7 +185,7 @@ // Set ShouldDoFullPaintInvalidation flag to all objects in the first line of // this block-level fragment. - void SetShouldDoFullPaintInvalidationForFirstLine(); + void SetShouldDoFullPaintInvalidationForFirstLine() const; // DisplayItemClient methods. String DebugName() const override; @@ -255,7 +255,7 @@ // When the LayoutObject is an inline block, it belongs to an inline // formatting context while it creates its own for its descendants. This // function always returns the one it belongs to. - static NGPaintFragment* GetForInlineContainer(const LayoutObject*); + static const NGPaintFragment* GetForInlineContainer(const LayoutObject*); // Returns a range of NGPaintFragment in an inline formatting context that are // for a LayoutObject. @@ -320,7 +320,7 @@ // Re-compute ink overflow of children and return the union. PhysicalRect RecalcInkOverflow(); - PhysicalRect RecalcContentsInkOverflow(); + PhysicalRect RecalcContentsInkOverflow() const; // This fragment will use the layout object's visual rect. const LayoutObject& VisualRectLayoutObject(bool& this_as_inline_box) const;
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal_test.cc b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal_test.cc index ca6e3ef..30d15d5 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal_test.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal_test.cc
@@ -59,7 +59,7 @@ } LayoutBlockFlow* layout_block_flow_; - NGPaintFragment* root_fragment_; + const NGPaintFragment* root_fragment_; }; TEST_F(NGPaintFragmentTraversalTest, MoveToNext) {
diff --git a/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc b/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc index 80dcd81..028504f 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc
@@ -192,18 +192,20 @@ )HTML"); InvalidateAll(RootPaintController()); - DisplayItemClient& container1 = + const DisplayItemClient& container1 = *GetDisplayItemClientFromElementId("container1"); - DisplayItemClient& content1 = *GetDisplayItemClientFromElementId("content1"); - DisplayItemClient& container2 = + const DisplayItemClient& content1 = + *GetDisplayItemClientFromElementId("content1"); + const DisplayItemClient& container2 = *GetDisplayItemClientFromElementId("container2"); - DisplayItemClient& content2a = + const DisplayItemClient& content2a = *GetDisplayItemClientFromElementId("content2a"); - DisplayItemClient& content2b = + const DisplayItemClient& content2b = *GetDisplayItemClientFromElementId("content2b"); - DisplayItemClient& container3 = + const DisplayItemClient& container3 = *GetDisplayItemClientFromElementId("container3"); - DisplayItemClient& content3 = *GetDisplayItemClientFromElementId("content3"); + const DisplayItemClient& content3 = + *GetDisplayItemClientFromElementId("content3"); GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint(); Paint(IntRect(0, 0, 400, 300)); @@ -287,12 +289,14 @@ // PaintResult of all subsequences will be MayBeClippedByCullRect. Paint(IntRect(0, 0, 50, 300)); - DisplayItemClient& container1 = + const DisplayItemClient& container1 = *GetDisplayItemClientFromElementId("container1"); - DisplayItemClient& content1 = *GetDisplayItemClientFromElementId("content1"); - DisplayItemClient& container2 = + const DisplayItemClient& content1 = + *GetDisplayItemClientFromElementId("content1"); + const DisplayItemClient& container2 = *GetDisplayItemClientFromElementId("container2"); - DisplayItemClient& content2 = *GetDisplayItemClientFromElementId("content2"); + const DisplayItemClient& content2 = + *GetDisplayItemClientFromElementId("content2"); const auto& background_display_item_client = ViewScrollingBackgroundClient(); EXPECT_THAT(RootPaintController().GetDisplayItemList(),
diff --git a/third_party/blink/renderer/core/testing/core_unit_test_helper.h b/third_party/blink/renderer/core/testing/core_unit_test_helper.h index b8f134e..7f525260 100644 --- a/third_party/blink/renderer/core/testing/core_unit_test_helper.h +++ b/third_party/blink/renderer/core/testing/core_unit_test_helper.h
@@ -141,7 +141,7 @@ return ToLayoutBoxModelObject(GetLayoutObjectByElementId(id))->Layer(); } - DisplayItemClient* GetDisplayItemClientFromLayoutObject( + const DisplayItemClient* GetDisplayItemClientFromLayoutObject( LayoutObject* obj) const { LayoutNGBlockFlow* block_flow = ToLayoutNGBlockFlowOrNull(obj); if (block_flow && block_flow->PaintFragment()) @@ -149,7 +149,8 @@ return obj; } - DisplayItemClient* GetDisplayItemClientFromElementId(const char* id) const { + const DisplayItemClient* GetDisplayItemClientFromElementId( + const char* id) const { return GetDisplayItemClientFromLayoutObject(GetLayoutObjectByElementId(id)); }
diff --git a/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js b/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js index c2cc71c..81b20b2 100644 --- a/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js +++ b/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js
@@ -453,13 +453,13 @@ if (entry.isDirectory) return; - entry.file(this._onLoadFromFile.bind(this)); + entry.file(this.onLoadFromFile.bind(this)); } /** * @param {!File} file */ - async _onLoadFromFile(file) { + async onLoadFromFile(file) { const outputStream = new Common.StringOutputStream(); const reader = new Bindings.ChunkedFileReader(file, /* chunkSize */ 10000000); const success = await reader.read(outputStream); @@ -1212,7 +1212,7 @@ } footerSection.appendItem(Common.UIString('Copy all as HAR'), this._copyAll.bind(this)); - contextMenu.saveSection().appendItem(Common.UIString('Save all as HAR with content'), this._exportAll.bind(this)); + contextMenu.saveSection().appendItem(ls`Save all as HAR with content`, this.exportAll.bind(this)); contextMenu.editSection().appendItem(Common.UIString('Clear browser cache'), this._clearBrowserCache.bind(this)); contextMenu.editSection().appendItem( @@ -1325,7 +1325,7 @@ InspectorFrontendHost.copyText(commands); } - async _exportAll() { + async exportAll() { const url = SDK.targetManager.mainTarget().inspectedURL(); const parsedURL = url.asParsedURL(); const filename = parsedURL ? parsedURL.host : 'network-log';
diff --git a/third_party/blink/renderer/devtools/front_end/network/NetworkPanel.js b/third_party/blink/renderer/devtools/front_end/network/NetworkPanel.js index 6bbf1a8..6e8a942 100644 --- a/third_party/blink/renderer/devtools/front_end/network/NetworkPanel.js +++ b/third_party/blink/renderer/devtools/front_end/network/NetworkPanel.js
@@ -118,6 +118,10 @@ new Network.NetworkLogView(this._filterBar, this._progressBarContainer, this._networkLogLargeRowsSetting); this._splitWidget.setSidebarWidget(this._networkLogView); + this._fileSelectorElement = + UI.createFileSelectorElement(this._networkLogView.onLoadFromFile.bind(this._networkLogView)); + panel.element.appendChild(this._fileSelectorElement); + this._detailsWidget = new UI.VBox(); this._detailsWidget.element.classList.add('network-details-view'); this._splitWidget.setMainWidget(this._detailsWidget); @@ -238,6 +242,14 @@ new UI.ToolbarSettingCheckbox(Common.moduleSetting('network.group-by-frame'), '', ls`Group by frame`)); settingsToolbarRight.appendToolbarItem( new UI.ToolbarSettingCheckbox(this._networkRecordFilmStripSetting, '', ls`Capture screenshots`)); + + this._panelToolbar.appendSeparator(); + const importHarButton = new UI.ToolbarButton(ls`Import HAR file...`, 'largeicon-load'); + importHarButton.addEventListener(UI.ToolbarButton.Events.Click, () => this._fileSelectorElement.click(), this); + this._panelToolbar.appendToolbarItem(importHarButton); + const exportHarButton = new UI.ToolbarButton(ls`Export all as HAR with content...`, 'largeicon-download'); + exportHarButton.addEventListener(UI.ToolbarButton.Events.Click, () => this._networkLogView.exportAll(), this); + this._panelToolbar.appendToolbarItem(exportHarButton); } _updateSettingsPaneVisibility() {
diff --git a/third_party/blink/renderer/modules/background_sync/service_worker_registration_sync.cc b/third_party/blink/renderer/modules/background_sync/service_worker_registration_sync.cc index 0ceffbf..758de35 100644 --- a/third_party/blink/renderer/modules/background_sync/service_worker_registration_sync.cc +++ b/third_party/blink/renderer/modules/background_sync/service_worker_registration_sync.cc
@@ -37,8 +37,12 @@ } SyncManager* ServiceWorkerRegistrationSync::sync() { - if (!sync_manager_) - sync_manager_ = SyncManager::Create(registration_); + if (!sync_manager_) { + ExecutionContext* execution_context = registration_->GetExecutionContext(); + sync_manager_ = SyncManager::Create( + registration_, + execution_context->GetTaskRunner(TaskType::kInternalWorker)); + } return sync_manager_.Get(); }
diff --git a/third_party/blink/renderer/modules/background_sync/sync_manager.cc b/third_party/blink/renderer/modules/background_sync/sync_manager.cc index ac40268..15360ce 100644 --- a/third_party/blink/renderer/modules/background_sync/sync_manager.cc +++ b/third_party/blink/renderer/modules/background_sync/sync_manager.cc
@@ -18,8 +18,9 @@ namespace blink { -SyncManager::SyncManager(ServiceWorkerRegistration* registration) - : registration_(registration) { +SyncManager::SyncManager(ServiceWorkerRegistration* registration, + scoped_refptr<base::SequencedTaskRunner> task_runner) + : registration_(registration), task_runner_(std::move(task_runner)) { DCHECK(registration); } @@ -63,7 +64,7 @@ SyncManager::GetBackgroundSyncServicePtr() { if (!background_sync_service_.get()) { Platform::Current()->GetInterfaceProvider()->GetInterface( - mojo::MakeRequest(&background_sync_service_)); + mojo::MakeRequest(&background_sync_service_, task_runner_)); } return background_sync_service_; }
diff --git a/third_party/blink/renderer/modules/background_sync/sync_manager.h b/third_party/blink/renderer/modules/background_sync/sync_manager.h index 33eedf61..5eedef11 100644 --- a/third_party/blink/renderer/modules/background_sync/sync_manager.h +++ b/third_party/blink/renderer/modules/background_sync/sync_manager.h
@@ -21,11 +21,15 @@ DEFINE_WRAPPERTYPEINFO(); public: - static SyncManager* Create(ServiceWorkerRegistration* registration) { - return MakeGarbageCollected<SyncManager>(registration); + static SyncManager* Create( + ServiceWorkerRegistration* registration, + scoped_refptr<base::SequencedTaskRunner> task_runner) { + return MakeGarbageCollected<SyncManager>(registration, + std::move(task_runner)); } - explicit SyncManager(ServiceWorkerRegistration*); + SyncManager(ServiceWorkerRegistration*, + scoped_refptr<base::SequencedTaskRunner>); ScriptPromise registerFunction(ScriptState*, const String& tag); ScriptPromise getTags(ScriptState*); @@ -50,6 +54,7 @@ WTF::Vector<mojom::blink::SyncRegistrationOptionsPtr> registrations); Member<ServiceWorkerRegistration> registration_; + scoped_refptr<base::SequencedTaskRunner> task_runner_; mojom::blink::BackgroundSyncServicePtr background_sync_service_; };
diff --git a/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc b/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc index 771991ca..9c40aec 100644 --- a/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc +++ b/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc
@@ -276,7 +276,7 @@ if (processing_events_) return; - base::AutoReset<bool>(&processing_events_, true); + base::AutoReset<bool> processing_events_reset(&processing_events_, true); if (StartUpdatingIfAttached()) { if (GetPage()->IsPageVisible()) { // Allocate a buffer to hold the new gamepad state, if needed. @@ -342,6 +342,8 @@ void NavigatorGamepad::DispatchGamepadEvent(const AtomicString& event_name, Gamepad* gamepad) { + // Ensure that we're blocking re-entrancy. + DCHECK(processing_events_); DCHECK(has_connection_event_listener_); DCHECK(gamepad); DomWindow()->DispatchEvent(*GamepadEvent::Create(
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc index b87af68c..a6181fa7 100644 --- a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc +++ b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc
@@ -32,6 +32,24 @@ void WebGL2ComputeRenderingContextBase::InitializeNewContext() { DCHECK(!isContextLost()); + DCHECK(GetDrawingBuffer()); + + bound_atomic_counter_buffer_ = nullptr; + bound_shader_storage_buffer_ = nullptr; + + GLint max_atomic_counter_buffer_bindings = 0; + ContextGL()->GetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, + &max_atomic_counter_buffer_bindings); + bound_indexed_atomic_counter_buffers_.clear(); + bound_indexed_atomic_counter_buffers_.resize( + max_atomic_counter_buffer_bindings); + + GLint max_shader_storage_buffer_bindings = 0; + ContextGL()->GetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, + &max_shader_storage_buffer_bindings); + bound_indexed_shader_storage_buffers_.clear(); + bound_indexed_shader_storage_buffers_.resize( + max_shader_storage_buffer_bindings); WebGL2RenderingContextBase::InitializeNewContext(); } @@ -333,7 +351,51 @@ } } +ScriptValue WebGL2ComputeRenderingContextBase::getIndexedParameter( + ScriptState* script_state, + GLenum target, + GLuint index) { + if (isContextLost()) + return ScriptValue::CreateNull(script_state); + + switch (target) { + case GL_ATOMIC_COUNTER_BUFFER_BINDING: + if (index >= bound_indexed_atomic_counter_buffers_.size()) { + SynthesizeGLError(GL_INVALID_VALUE, "getIndexedParameter", + "index out of range"); + return ScriptValue::CreateNull(script_state); + } + return WebGLAny(script_state, + bound_indexed_atomic_counter_buffers_[index].Get()); + case GL_SHADER_STORAGE_BUFFER_BINDING: + if (index >= bound_indexed_shader_storage_buffers_.size()) { + SynthesizeGLError(GL_INVALID_VALUE, "getIndexedParameter", + "index out of range"); + return ScriptValue::CreateNull(script_state); + } + return WebGLAny(script_state, + bound_indexed_shader_storage_buffers_[index].Get()); + case GL_MAX_COMPUTE_WORK_GROUP_COUNT: + case GL_MAX_COMPUTE_WORK_GROUP_SIZE: + case GL_ATOMIC_COUNTER_BUFFER_SIZE: + case GL_ATOMIC_COUNTER_BUFFER_START: + case GL_SHADER_STORAGE_BUFFER_SIZE: + case GL_SHADER_STORAGE_BUFFER_START: { + GLint64 value = -1; + ContextGL()->GetInteger64i_v(target, index, &value); + return WebGLAny(script_state, value); + } + default: + return WebGL2RenderingContextBase::getIndexedParameter( + script_state, target, index); + } +} + void WebGL2ComputeRenderingContextBase::Trace(blink::Visitor* visitor) { + visitor->Trace(bound_atomic_counter_buffer_); + visitor->Trace(bound_indexed_atomic_counter_buffers_); + visitor->Trace(bound_shader_storage_buffer_); + visitor->Trace(bound_indexed_shader_storage_buffers_); WebGL2RenderingContextBase::Trace(visitor); } @@ -361,4 +423,179 @@ } } +bool WebGL2ComputeRenderingContextBase::ValidateShaderType( + const char* function_name, + GLenum shader_type) { + switch (shader_type) { + case GL_COMPUTE_SHADER: + return true; + default: + return WebGL2RenderingContextBase::ValidateShaderType( + function_name, shader_type); + } +} + +bool WebGL2ComputeRenderingContextBase::ValidateBufferTarget( + const char* function_name, + GLenum target) { + switch (target) { + case GL_ATOMIC_COUNTER_BUFFER: + case GL_SHADER_STORAGE_BUFFER: + return true; + default: + return WebGL2RenderingContextBase::ValidateBufferTarget( + function_name, target); + } +} + +WebGLBuffer* WebGL2ComputeRenderingContextBase::ValidateBufferDataTarget( + const char* function_name, + GLenum target) { + WebGLBuffer* buffer = nullptr; + switch (target) { + case GL_ATOMIC_COUNTER_BUFFER: + buffer = bound_atomic_counter_buffer_.Get(); + break; + case GL_SHADER_STORAGE_BUFFER: + buffer = bound_shader_storage_buffer_.Get(); + break; + default: + return WebGL2RenderingContextBase::ValidateBufferDataTarget( + function_name, target); + } + if (!buffer) { + SynthesizeGLError(GL_INVALID_OPERATION, function_name, "no buffer"); + return nullptr; + } + return buffer; +} + +bool WebGL2ComputeRenderingContextBase::ValidateAndUpdateBufferBindTarget( + const char* function_name, + GLenum target, + WebGLBuffer* buffer) { + if (!ValidateBufferTarget(function_name, target)) + return false; + + if (buffer && + !ValidateBufferTargetCompatibility(function_name, target, buffer)) + return false; + + switch (target) { + case GL_ATOMIC_COUNTER_BUFFER: + bound_atomic_counter_buffer_ = buffer; + break; + case GL_SHADER_STORAGE_BUFFER: + bound_shader_storage_buffer_ = buffer; + break; + default: + return WebGL2RenderingContextBase::ValidateAndUpdateBufferBindTarget( + function_name, target, buffer); + } + + if (buffer && !buffer->GetInitialTarget()) + buffer->SetInitialTarget(target); + return true; +} + +void WebGL2ComputeRenderingContextBase::RemoveBoundBuffer(WebGLBuffer* buffer) { + if (bound_atomic_counter_buffer_ == buffer) + bound_atomic_counter_buffer_ = nullptr; + if (bound_shader_storage_buffer_ == buffer) + bound_shader_storage_buffer_ = nullptr; + + WebGL2RenderingContextBase::RemoveBoundBuffer(buffer); +} + +bool WebGL2ComputeRenderingContextBase::ValidateBufferTargetCompatibility( + const char* function_name, + GLenum target, + WebGLBuffer* buffer) { + DCHECK(buffer); + + switch (buffer->GetInitialTarget()) { + case GL_ELEMENT_ARRAY_BUFFER: + switch (target) { + case GL_ATOMIC_COUNTER_BUFFER: + case GL_SHADER_STORAGE_BUFFER: + SynthesizeGLError( + GL_INVALID_OPERATION, function_name, + "element array buffers can not be bound to a different target"); + + return false; + default: + break; + } + break; + case GL_ATOMIC_COUNTER_BUFFER: + case GL_SHADER_STORAGE_BUFFER: + if (target == GL_ELEMENT_ARRAY_BUFFER) { + SynthesizeGLError(GL_INVALID_OPERATION, function_name, + "buffers bound to non ELEMENT_ARRAY_BUFFER targets " + "can not be bound to ELEMENT_ARRAY_BUFFER target"); + return false; + } + return true; + default: + break; + } + + return WebGL2RenderingContextBase::ValidateBufferTargetCompatibility( + function_name, target, buffer); +} + +bool WebGL2ComputeRenderingContextBase::ValidateBufferBaseTarget( + const char* function_name, + GLenum target) { + switch (target) { + case GL_ATOMIC_COUNTER_BUFFER: + case GL_SHADER_STORAGE_BUFFER: + return true; + default: + return WebGL2RenderingContextBase::ValidateBufferBaseTarget( + function_name, target); + } +} + +bool WebGL2ComputeRenderingContextBase::ValidateAndUpdateBufferBindBaseTarget( + const char* function_name, + GLenum target, + GLuint index, + WebGLBuffer* buffer) { + if (!ValidateBufferBaseTarget(function_name, target)) + return false; + + if (buffer && + !ValidateBufferTargetCompatibility(function_name, target, buffer)) + return false; + + switch (target) { + case GL_ATOMIC_COUNTER_BUFFER: + if (index >= bound_indexed_atomic_counter_buffers_.size()) { + SynthesizeGLError(GL_INVALID_VALUE, function_name, + "index out of range"); + return false; + } + bound_indexed_atomic_counter_buffers_[index] = buffer; + bound_atomic_counter_buffer_ = buffer; + break; + case GL_SHADER_STORAGE_BUFFER: + if (index >= bound_indexed_shader_storage_buffers_.size()) { + SynthesizeGLError(GL_INVALID_VALUE, function_name, + "index out of range"); + return false; + } + bound_indexed_shader_storage_buffers_[index] = buffer; + bound_shader_storage_buffer_ = buffer; + break; + default: + return WebGL2RenderingContextBase::ValidateAndUpdateBufferBindBaseTarget( + function_name, target, index, buffer); + } + + if (buffer && !buffer->GetInitialTarget()) + buffer->SetInitialTarget(target); + return true; +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h index 7383987..a713d1f4 100644 --- a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h +++ b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h
@@ -59,6 +59,11 @@ void InitializeNewContext() override; ScriptValue getParameter(ScriptState*, GLenum pname) override; + /* WebGL2RenderingContextBase overrides */ + ScriptValue getIndexedParameter(ScriptState*, + GLenum target, + GLuint index) override; + void Trace(blink::Visitor*) override; protected: @@ -72,6 +77,34 @@ GLint location, WebGLProgram* program, GLenum program_interface); + + /* WebGLRenderingContextBase overrides */ + bool ValidateShaderType(const char* function_name, + GLenum shader_type) override; + bool ValidateBufferTarget(const char* function_name, GLenum target) override; + WebGLBuffer* ValidateBufferDataTarget(const char* function_name, + GLenum target) override; + bool ValidateAndUpdateBufferBindTarget(const char* function_name, + GLenum target, + WebGLBuffer*) override; + void RemoveBoundBuffer(WebGLBuffer*) override; + + /* WebGL2RenderingContextBase overrides */ + bool ValidateBufferTargetCompatibility(const char* function_name, + GLenum target, + WebGLBuffer*) override; + bool ValidateBufferBaseTarget(const char* function_name, + GLenum target) override; + bool ValidateAndUpdateBufferBindBaseTarget(const char* function_name, + GLenum target, + GLuint index, + WebGLBuffer*) override; + + Member<WebGLBuffer> bound_atomic_counter_buffer_; + Member<WebGLBuffer> bound_shader_storage_buffer_; + + HeapVector<Member<WebGLBuffer>> bound_indexed_atomic_counter_buffers_; + HeapVector<Member<WebGLBuffer>> bound_indexed_shader_storage_buffers_; }; DEFINE_TYPE_CASTS(WebGL2ComputeRenderingContextBase,
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc index 787aeae..3f94f1c 100644 --- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc +++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc
@@ -170,8 +170,6 @@ bound_pixel_unpack_buffer_ = nullptr; bound_transform_feedback_buffer_ = nullptr; bound_uniform_buffer_ = nullptr; - bound_atomic_counter_buffer_ = nullptr; - bound_shader_storage_buffer_ = nullptr; current_boolean_occlusion_query_ = nullptr; current_transform_feedback_primitives_written_query_ = nullptr; @@ -201,22 +199,6 @@ bound_indexed_uniform_buffers_.resize(max_uniform_buffer_bindings); max_bound_uniform_buffer_index_ = 0; - if (ContextType() == Platform::kWebGL2ComputeContextType) { - GLint max_atomic_counter_buffer_bindings = 0; - ContextGL()->GetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, - &max_atomic_counter_buffer_bindings); - bound_indexed_atomic_counter_buffers_.clear(); - bound_indexed_atomic_counter_buffers_.resize( - max_atomic_counter_buffer_bindings); - - GLint max_shader_storage_buffer_bindings = 0; - ContextGL()->GetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, - &max_shader_storage_buffer_bindings); - bound_indexed_shader_storage_buffers_.clear(); - bound_indexed_shader_storage_buffers_.resize( - max_shader_storage_buffer_bindings); - } - pack_row_length_ = 0; pack_skip_pixels_ = 0; pack_skip_rows_ = 0; @@ -4667,34 +4649,6 @@ } return WebGLAny(script_state, bound_indexed_uniform_buffers_[index].Get()); - case GL_ATOMIC_COUNTER_BUFFER_BINDING: { - if (ContextType() != Platform::kWebGL2ComputeContextType) { - SynthesizeGLError(GL_INVALID_ENUM, "getIndexedParameter", - "invalid parameter name"); - return ScriptValue::CreateNull(script_state); - } - if (index >= bound_indexed_atomic_counter_buffers_.size()) { - SynthesizeGLError(GL_INVALID_VALUE, "getIndexedParameter", - "index out of range"); - return ScriptValue::CreateNull(script_state); - } - return WebGLAny(script_state, - bound_indexed_atomic_counter_buffers_[index].Get()); - } - case GL_SHADER_STORAGE_BUFFER_BINDING: { - if (ContextType() != Platform::kWebGL2ComputeContextType) { - SynthesizeGLError(GL_INVALID_ENUM, "getIndexedParameter", - "invalid parameter name"); - return ScriptValue::CreateNull(script_state); - } - if (index >= bound_indexed_shader_storage_buffers_.size()) { - SynthesizeGLError(GL_INVALID_VALUE, "getIndexedParameter", - "index out of range"); - return ScriptValue::CreateNull(script_state); - } - return WebGLAny(script_state, - bound_indexed_shader_storage_buffers_[index].Get()); - } case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: case GL_TRANSFORM_FEEDBACK_BUFFER_START: case GL_UNIFORM_BUFFER_SIZE: @@ -4703,22 +4657,6 @@ ContextGL()->GetInteger64i_v(target, index, &value); return WebGLAny(script_state, value); } - case GL_MAX_COMPUTE_WORK_GROUP_COUNT: - case GL_MAX_COMPUTE_WORK_GROUP_SIZE: - case GL_ATOMIC_COUNTER_BUFFER_SIZE: - case GL_ATOMIC_COUNTER_BUFFER_START: - case GL_SHADER_STORAGE_BUFFER_SIZE: - case GL_SHADER_STORAGE_BUFFER_START: { - if (ContextType() != Platform::kWebGL2ComputeContextType) { - SynthesizeGLError(GL_INVALID_ENUM, "getIndexedParameter", - "invalid parameter name"); - return ScriptValue::CreateNull(script_state); - } - GLint64 value = -1; - ContextGL()->GetInteger64i_v(target, index, &value); - return WebGLAny(script_state, value); - } - default: SynthesizeGLError(GL_INVALID_ENUM, "getIndexedParameter", "invalid parameter name"); @@ -5262,8 +5200,6 @@ case GL_PIXEL_UNPACK_BUFFER: case GL_TRANSFORM_FEEDBACK_BUFFER: case GL_UNIFORM_BUFFER: - case GL_ATOMIC_COUNTER_BUFFER: - case GL_SHADER_STORAGE_BUFFER: SynthesizeGLError( GL_INVALID_OPERATION, function_name, "element array buffers can not be bound to a different target"); @@ -5280,8 +5216,6 @@ case GL_PIXEL_UNPACK_BUFFER: case GL_UNIFORM_BUFFER: case GL_TRANSFORM_FEEDBACK_BUFFER: - case GL_ATOMIC_COUNTER_BUFFER: - case GL_SHADER_STORAGE_BUFFER: if (target == GL_ELEMENT_ARRAY_BUFFER) { SynthesizeGLError(GL_INVALID_OPERATION, function_name, "buffers bound to non ELEMENT_ARRAY_BUFFER targets " @@ -5308,13 +5242,6 @@ case GL_TRANSFORM_FEEDBACK_BUFFER: case GL_UNIFORM_BUFFER: return true; - case GL_ATOMIC_COUNTER_BUFFER: - case GL_SHADER_STORAGE_BUFFER: - if (ContextType() != Platform::kWebGL2ComputeContextType) { - SynthesizeGLError(GL_INVALID_ENUM, function_name, "invalid target"); - return false; - } - return true; default: SynthesizeGLError(GL_INVALID_ENUM, function_name, "invalid target"); return false; @@ -5357,12 +5284,6 @@ case GL_UNIFORM_BUFFER: bound_uniform_buffer_ = buffer; break; - case GL_ATOMIC_COUNTER_BUFFER: - bound_atomic_counter_buffer_ = buffer; - break; - case GL_SHADER_STORAGE_BUFFER: - bound_shader_storage_buffer_ = buffer; - break; default: NOTREACHED(); break; @@ -5380,13 +5301,6 @@ case GL_TRANSFORM_FEEDBACK_BUFFER: case GL_UNIFORM_BUFFER: return true; - case GL_ATOMIC_COUNTER_BUFFER: - case GL_SHADER_STORAGE_BUFFER: - if (ContextType() != Platform::kWebGL2ComputeContextType) { - SynthesizeGLError(GL_INVALID_ENUM, function_name, "invalid target"); - return false; - } - return true; default: SynthesizeGLError(GL_INVALID_ENUM, function_name, "invalid target"); return false; @@ -5438,24 +5352,6 @@ max_bound_uniform_buffer_index_ = i; } break; - case GL_ATOMIC_COUNTER_BUFFER: - if (index >= bound_indexed_atomic_counter_buffers_.size()) { - SynthesizeGLError(GL_INVALID_VALUE, function_name, - "index out of range"); - return false; - } - bound_indexed_atomic_counter_buffers_[index] = buffer; - bound_atomic_counter_buffer_ = buffer; - break; - case GL_SHADER_STORAGE_BUFFER: - if (index >= bound_indexed_shader_storage_buffers_.size()) { - SynthesizeGLError(GL_INVALID_VALUE, function_name, - "index out of range"); - return false; - } - bound_indexed_shader_storage_buffers_[index] = buffer; - bound_shader_storage_buffer_ = buffer; - break; default: NOTREACHED(); break; @@ -5819,10 +5715,6 @@ visitor->Trace(bound_transform_feedback_buffer_); visitor->Trace(bound_uniform_buffer_); visitor->Trace(bound_indexed_uniform_buffers_); - visitor->Trace(bound_atomic_counter_buffer_); - visitor->Trace(bound_indexed_atomic_counter_buffers_); - visitor->Trace(bound_shader_storage_buffer_); - visitor->Trace(bound_indexed_shader_storage_buffers_); visitor->Trace(current_boolean_occlusion_query_); visitor->Trace(current_transform_feedback_primitives_written_query_); visitor->Trace(current_elapsed_query_); @@ -5930,22 +5822,6 @@ case GL_UNIFORM_BUFFER: buffer = bound_uniform_buffer_.Get(); break; - case GL_ATOMIC_COUNTER_BUFFER: { - if (ContextType() != Platform::kWebGL2ComputeContextType) { - SynthesizeGLError(GL_INVALID_ENUM, function_name, "invalid target"); - return nullptr; - } - buffer = bound_atomic_counter_buffer_.Get(); - break; - } - case GL_SHADER_STORAGE_BUFFER: { - if (ContextType() != Platform::kWebGL2ComputeContextType) { - SynthesizeGLError(GL_INVALID_ENUM, function_name, "invalid target"); - return nullptr; - } - buffer = bound_shader_storage_buffer_.Get(); - break; - } default: SynthesizeGLError(GL_INVALID_ENUM, function_name, "invalid target"); return nullptr; @@ -6044,10 +5920,6 @@ bound_transform_feedback_buffer_ = nullptr; if (bound_uniform_buffer_ == buffer) bound_uniform_buffer_ = nullptr; - if (bound_atomic_counter_buffer_ == buffer) - bound_atomic_counter_buffer_ = nullptr; - if (bound_shader_storage_buffer_ == buffer) - bound_shader_storage_buffer_ = nullptr; transform_feedback_binding_->UnbindBuffer(buffer);
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h index 383a5ebc..54b02ee 100644 --- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h +++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h
@@ -907,7 +907,7 @@ /* Uniform Buffer Objects and Transform Feedback Buffers */ void bindBufferBase(GLenum, GLuint, WebGLBuffer*); void bindBufferRange(GLenum, GLuint, WebGLBuffer*, int64_t, int64_t); - ScriptValue getIndexedParameter(ScriptState*, GLenum, GLuint); + virtual ScriptValue getIndexedParameter(ScriptState*, GLenum, GLuint); Vector<GLuint> getUniformIndices(WebGLProgram*, const Vector<String>&); ScriptValue getActiveUniforms(ScriptState*, WebGLProgram*, @@ -1021,13 +1021,16 @@ bool IsBufferBoundToTransformFeedback(WebGLBuffer*); bool IsBufferBoundToNonTransformFeedback(WebGLBuffer*); - bool ValidateBufferTargetCompatibility(const char*, GLenum, WebGLBuffer*); + virtual bool ValidateBufferTargetCompatibility(const char*, + GLenum, + WebGLBuffer*); - bool ValidateBufferBaseTarget(const char* function_name, GLenum target); - bool ValidateAndUpdateBufferBindBaseTarget(const char* function_name, - GLenum, - GLuint, - WebGLBuffer*); + virtual bool ValidateBufferBaseTarget(const char* function_name, + GLenum target); + virtual bool ValidateAndUpdateBufferBindBaseTarget(const char* function_name, + GLenum, + GLuint, + WebGLBuffer*); WebGLImageConversion::PixelStoreParams GetPackPixelStoreParams() override; WebGLImageConversion::PixelStoreParams GetUnpackPixelStoreParams( @@ -1126,11 +1129,7 @@ Member<WebGLBuffer> bound_pixel_unpack_buffer_; Member<WebGLBuffer> bound_transform_feedback_buffer_; Member<WebGLBuffer> bound_uniform_buffer_; - Member<WebGLBuffer> bound_atomic_counter_buffer_; - Member<WebGLBuffer> bound_shader_storage_buffer_; - HeapVector<Member<WebGLBuffer>> bound_indexed_atomic_counter_buffers_; - HeapVector<Member<WebGLBuffer>> bound_indexed_shader_storage_buffers_; HeapVector<Member<WebGLBuffer>> bound_indexed_uniform_buffers_; GLint max_transform_feedback_separate_attribs_; wtf_size_t max_bound_uniform_buffer_index_;
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc index 66ffd77..8e88a27 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -2331,25 +2331,6 @@ bound_vertex_array_object_ = default_vertex_array_object_; } -bool WebGLRenderingContextBase::ValidateShaderType(const char* function_name, - GLenum shader_type) { - switch (shader_type) { - case GL_VERTEX_SHADER: - case GL_FRAGMENT_SHADER: - return true; - case GL_COMPUTE_SHADER: - if (context_type_ != Platform::kWebGL2ComputeContextType) { - SynthesizeGLError(GL_INVALID_ENUM, function_name, - "invalid shader type"); - return false; - } - return true; - default: - SynthesizeGLError(GL_INVALID_ENUM, function_name, "invalid shader type"); - return false; - } -} - WebGLShader* WebGLRenderingContextBase::createShader(GLenum type) { if (isContextLost()) return nullptr; @@ -7009,6 +6990,18 @@ return true; } +bool WebGLRenderingContextBase::ValidateShaderType(const char* function_name, + GLenum shader_type) { + switch (shader_type) { + case GL_VERTEX_SHADER: + case GL_FRAGMENT_SHADER: + return true; + default: + SynthesizeGLError(GL_INVALID_ENUM, function_name, "invalid shader type"); + return false; + } +} + void WebGLRenderingContextBase::AddExtensionSupportedFormatsTypes() { if (!is_oes_texture_float_formats_types_added_ && ExtensionEnabled(kOESTextureFloatName)) {
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h index b57ae0d..17b89bdc 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
@@ -1195,6 +1195,9 @@ // 2.0. bool ValidateShaderSource(const String&); + virtual bool ValidateShaderType(const char* function_name, + GLenum shader_type); + // Helper function to check texture binding target and texture bound to the // target. Generate GL errors and return 0 if target is invalid or texture // bound is null. Otherwise, return the texture bound to the target. @@ -1717,8 +1720,6 @@ bool flip_y); bool CanUseTexImageViaGPU(GLenum format, GLenum type); - bool ValidateShaderType(const char* function_name, GLenum shader_type); - const Platform::ContextType context_type_; bool IsPaintable() const final { return GetDrawingBuffer(); }
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc index eaedff6..490b73f 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_view.cc
@@ -432,6 +432,9 @@ float advance_so_far = initial_advance; for (const auto& part : parts_) { + if (!part->NumGlyphs()) + continue; + const auto& run = part->run_; unsigned graphemes_in_cluster = 1; float cluster_advance = 0;
diff --git a/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc b/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc index 20b03cb3..c90fe8b 100644 --- a/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc +++ b/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
@@ -42,19 +42,17 @@ base::WeakPtr<WebGraphicsContext3DProviderWrapper>&& context_provider_wrapper, IntSize mailbox_size, - MailboxType mailbox_type, std::unique_ptr<viz::SingleReleaseCallback> release_callback) { return base::AdoptRef(new AcceleratedStaticBitmapImage( mailbox, sync_token, texture_id, std::move(context_provider_wrapper), - mailbox_size, mailbox_type, std::move(release_callback))); + mailbox_size, std::move(release_callback))); } AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage( sk_sp<SkImage> image, base::WeakPtr<WebGraphicsContext3DProviderWrapper>&& context_provider_wrapper) - : paint_image_content_id_(cc::PaintImage::GetNextContentId()), - mailbox_type_(MailboxType::kDeprecatedMailbox) { + : paint_image_content_id_(cc::PaintImage::GetNextContentId()) { CHECK(image && image->isTextureBacked()); texture_holder_ = std::make_unique<SkiaTextureHolder>( std::move(image), std::move(context_provider_wrapper)); @@ -67,10 +65,8 @@ base::WeakPtr<WebGraphicsContext3DProviderWrapper>&& context_provider_wrapper, IntSize mailbox_size, - MailboxType mailbox_type, std::unique_ptr<viz::SingleReleaseCallback> release_callback) : paint_image_content_id_(cc::PaintImage::GetNextContentId()), - mailbox_type_(mailbox_type), release_callback_(std::move(release_callback)) { texture_holder_ = std::make_unique<MailboxTextureHolder>( mailbox, sync_token, texture_id, std::move(context_provider_wrapper), @@ -178,11 +174,14 @@ // that the source and destination context or on the same stream. EnsureMailbox(kUnverifiedSyncToken, GL_NEAREST); + DCHECK(texture_holder_->IsMailboxTextureHolder()); + bool is_shared_image = texture_holder_->GetMailbox().IsSharedImage(); + // Get a texture id that |destProvider| knows about and copy from it. dest_gl->WaitSyncTokenCHROMIUM( texture_holder_->GetSyncToken().GetConstData()); GLuint source_texture_id; - if (mailbox_type_ == MailboxType::kSharedImageId) { + if (is_shared_image) { source_texture_id = dest_gl->CreateAndTexStorage2DSharedImageCHROMIUM( texture_holder_->GetMailbox().name); dest_gl->BeginSharedImageAccessDirectCHROMIUM( @@ -197,7 +196,7 @@ source_sub_rectangle.Y(), source_sub_rectangle.Width(), source_sub_rectangle.Height(), unpack_flip_y ? GL_FALSE : GL_TRUE, GL_FALSE, unpack_premultiply_alpha ? GL_FALSE : GL_TRUE); - if (mailbox_type_ == MailboxType::kSharedImageId) { + if (is_shared_image) { dest_gl->EndSharedImageAccessDirectCHROMIUM(source_texture_id); } // This drops the |destGL| context's reference on our |m_mailbox|, but it's @@ -283,10 +282,8 @@ if (texture_holder_->IsSkiaTextureHolder()) return; - const bool backed_by_shared_image = - mailbox_type_ == MailboxType::kSharedImageId; - texture_holder_ = std::make_unique<SkiaTextureHolder>( - std::move(texture_holder_), backed_by_shared_image); + texture_holder_ = + std::make_unique<SkiaTextureHolder>(std::move(texture_holder_)); } void AcceleratedStaticBitmapImage::EnsureMailbox(MailboxSyncMode mode,
diff --git a/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h b/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h index d9e1a8e..58da304 100644 --- a/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h +++ b/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h
@@ -27,8 +27,6 @@ class PLATFORM_EXPORT AcceleratedStaticBitmapImage final : public StaticBitmapImage { public: - enum class MailboxType { kSharedImageId, kDeprecatedMailbox }; - ~AcceleratedStaticBitmapImage() override; // SkImage with a texture backing. static scoped_refptr<AcceleratedStaticBitmapImage> CreateFromSkImage( @@ -50,7 +48,6 @@ unsigned texture_id, base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&, IntSize mailbox_size, - MailboxType mailbox_type = MailboxType::kDeprecatedMailbox, std::unique_ptr<viz::SingleReleaseCallback> release_callback = nullptr); bool CurrentFrameKnownToBeOpaque() override; @@ -115,7 +112,6 @@ unsigned texture_id, base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&, IntSize mailbox_size, - MailboxType mailbox_type, std::unique_ptr<viz::SingleReleaseCallback> release_callback); void CreateImageFromMailboxIfNeeded(); @@ -133,7 +129,6 @@ base::WeakPtr<WebGraphicsContext3DProviderWrapper> original_skia_image_context_provider_wrapper_; - const MailboxType mailbox_type_; std::unique_ptr<viz::SingleReleaseCallback> release_callback_; };
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.cc b/third_party/blink/renderer/platform/graphics/canvas_resource.cc index cd927ea..f199c5b5 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -797,8 +797,7 @@ scoped_refptr<StaticBitmapImage> image = AcceleratedStaticBitmapImage::CreateFromWebGLContextImage( shared_image_mailbox_, GetSyncToken(), 0, ContextProviderWrapper(), - Size(), AcceleratedStaticBitmapImage::MailboxType::kSharedImageId, - std::move(release_callback)); + Size(), std::move(release_callback)); DCHECK(image); return image; }
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc index 9cc4219..adeb47f 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -65,10 +65,12 @@ } void PaintArtifactCompositor::EnableExtraDataForTesting() { - if (!extra_data_for_testing_enabled_) - SetNeedsUpdate(); + if (extra_data_for_testing_enabled_) + return; extra_data_for_testing_enabled_ = true; extra_data_for_testing_ = std::make_unique<ExtraDataForTesting>(); + // Ensure |extra_data_for_testing_| is populated. + SetNeedsUpdate(); } void PaintArtifactCompositor::SetTracksRasterInvalidations(bool should_track) {
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc index 330047d7..1b544a54 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -602,8 +602,7 @@ // in DrawingBuffer. return AcceleratedStaticBitmapImage::CreateFromWebGLContextImage( sk_image_mailbox, sk_image_sync_token, texture_id, - context_provider_->GetWeakPtr(), size_, - AcceleratedStaticBitmapImage::MailboxType::kSharedImageId); + context_provider_->GetWeakPtr(), size_); } scoped_refptr<DrawingBuffer::ColorBuffer>
diff --git a/third_party/blink/renderer/platform/graphics/graphics_context.cc b/third_party/blink/renderer/platform/graphics/graphics_context.cc index 6c28903..3e3eaadd 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_context.cc +++ b/third_party/blink/renderer/platform/graphics/graphics_context.cc
@@ -751,7 +751,6 @@ if (ContextDisabled()) return; - DCHECK(!rect.IsEmpty()); if (rect.IsEmpty()) return;
diff --git a/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc b/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc index 873d712..50267b7 100644 --- a/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc +++ b/third_party/blink/renderer/platform/graphics/skia_texture_holder.cc
@@ -23,8 +23,7 @@ image_(std::move(image)) {} SkiaTextureHolder::SkiaTextureHolder( - std::unique_ptr<TextureHolder> texture_holder, - bool backed_by_shared_image) + std::unique_ptr<TextureHolder> texture_holder) : TextureHolder(SharedGpuContext::ContextProviderWrapper()) { DCHECK(texture_holder->IsMailboxTextureHolder()); const gpu::Mailbox mailbox = texture_holder->GetMailbox(); @@ -41,7 +40,7 @@ shared_gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); GLuint shared_context_texture_id = 0u; - if (backed_by_shared_image) { + if (mailbox.IsSharedImage()) { shared_context_texture_id = shared_gl->CreateAndTexStorage2DSharedImageCHROMIUM(mailbox.name); shared_gl->BeginSharedImageAccessDirectCHROMIUM(
diff --git a/third_party/blink/renderer/platform/graphics/skia_texture_holder.h b/third_party/blink/renderer/platform/graphics/skia_texture_holder.h index 8c0a1043..33f51fd 100644 --- a/third_party/blink/renderer/platform/graphics/skia_texture_holder.h +++ b/third_party/blink/renderer/platform/graphics/skia_texture_holder.h
@@ -35,8 +35,7 @@ base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&); // This function consumes the mailbox in the input parameter and turn it into // a texture-backed SkImage. - SkiaTextureHolder(std::unique_ptr<TextureHolder>, - bool backed_by_shared_image); + SkiaTextureHolder(std::unique_ptr<TextureHolder>); private: // The image_ should always be texture-backed.
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint index 51aee5f..99811d9 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint +++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
@@ -391,17 +391,6 @@ crbug.com/909749 fast/events/touch/compositor-touch-hit-rects-global.html [ Failure ] crbug.com/909749 fast/events/touch/compositor-touch-hit-rects-non-composited-scroll.html [ Failure ] -# These were introduced by the new dirty bit on PaintArtifactCompositor. -crbug.com/909749 fast/events/touch/compositor-touch-hit-rects-animation.html [ Failure ] -crbug.com/909749 fast/events/touch/compositor-touch-hit-rects-many.html [ Failure ] -crbug.com/909749 fast/events/touch/compositor-touch-hit-rects-scroll.html [ Failure ] -crbug.com/909749 fast/events/touch/compositor-touch-hit-rects-squashing.html [ Failure ] -crbug.com/909749 fast/events/touch/compositor-touch-hit-rects-table.html [ Failure ] -crbug.com/909749 fast/events/touch/compositor-touch-hit-rects-transform-changed-nolayout.html [ Failure ] -crbug.com/909749 fast/events/touch/compositor-touch-hit-rects-visibility-hidden.html [ Failure ] -crbug.com/909749 fast/events/touch/compositor-touch-hit-rects.html [ Failure ] -crbug.com/909749 fast/events/touch/touch-rect-crash-on-unpromote-layer.html [ Failure ] - # Backdrop filter crbug.com/923429 css3/filters/backdrop-filter-basic-blur.html [ Failure ] crbug.com/923429 css3/filters/backdrop-filter-browser-zoom.html [ Failure ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index a87b8480..00350ea 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -1861,6 +1861,8 @@ crbug.com/626703 external/wpt/css/css-text/word-break/word-break-break-all-004.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/word-break/word-break-break-all-006.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/word-break/word-break-break-all-008.html [ Failure ] +crbug.com/964181 external/wpt/css/css-text/word-break/word-break-break-all-inline-004.html [ Failure ] +crbug.com/964181 external/wpt/css/css-text/word-break/word-break-break-all-inline-007.html [ Failure ] crbug.com/626703 [ Linux ] external/wpt/css/css-text/word-break/word-break-normal-bo-000.html [ Failure ] crbug.com/626703 [ Win ] external/wpt/css/css-text/word-break/word-break-normal-km-000.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/word-break/word-break-normal-my-000.html [ Failure ] @@ -2734,13 +2736,11 @@ crbug.com/626703 external/wpt/css/css-overflow/webkit-line-clamp-024.html [ Failure ] crbug.com/626703 external/wpt/css/css-overflow/webkit-line-clamp-010.html [ Failure ] crbug.com/626703 external/wpt/css/css-overflow/webkit-line-clamp-012.html [ Failure ] -crbug.com/626703 external/wpt/css/css-text/word-break/word-break-break-all-inline-007.html [ Failure ] crbug.com/626703 external/wpt/css/css-overflow/webkit-line-clamp-033.html [ Failure ] crbug.com/626703 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-width-005.html [ Failure ] crbug.com/626703 external/wpt/css/css-multicol/multicol-width-005.html [ Failure ] crbug.com/626703 virtual/layout_ng_experimental/external/wpt/css/css-multicol/multicol-width-004.html [ Failure ] crbug.com/626703 external/wpt/css/css-overflow/webkit-line-clamp-027.html [ Failure ] -crbug.com/626703 external/wpt/css/css-text/word-break/word-break-break-all-inline-004.html [ Failure ] crbug.com/626703 external/wpt/css/css-overflow/webkit-line-clamp-011.html [ Failure ] crbug.com/626703 external/wpt/css/css-overflow/webkit-line-clamp-013.html [ Failure ] crbug.com/626703 external/wpt/css/css-overflow/webkit-line-clamp-014.html [ Failure ] @@ -3242,7 +3242,6 @@ crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-horiz-002.xhtml [ Failure ] crbug.com/875411 external/wpt/svg/text/reftests/text-shape-inside-002.svg [ Failure ] crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-horiz-002.xhtml [ Failure ] -crbug.com/626703 [ Android ] virtual/media-gpu-accelerated/external/wpt/media-source/mediasource-play.html [ Crash ] crbug.com/626703 external/wpt/speech-api/SpeechSynthesis-speak-twice.html [ Timeout ] crbug.com/626703 external/wpt/speech-api/SpeechSynthesis-speak-without-activation-fails.tentative.html [ Timeout ] crbug.com/626703 virtual/speech-with-unified-autoplay/external/wpt/speech-api/SpeechSynthesis-speak-twice.html [ Timeout ] @@ -5634,3 +5633,6 @@ crbug.com/965137 [ Linux ] external/wpt/css/css-overflow/webkit-line-clamp-026.html [ Failure ] crbug.com/965134 [ Linux ] fast/events/pointerevents/multi-touch-events.html [ Failure ] crbug.com/965134 [ Linux ] virtual/mouseevent_fractional/fast/events/pointerevents/pointer-event-in-slop-region.html [ Failure ] +crbug.com/965356 [ Mac ] inspector-protocol/heap-profiler/heap-snapshot-merged-nodes.js [ Pass Failure ] +crbug.com/965356 [ Mac ] inspector-protocol/heap-profiler/heap-snapshot-with-event-listener.js [ Pass Failure ] +crbug.com/965134 [ Linux ] fast/events/pointerevents/pointer-event-in-slop-region.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-emphasis-unrepresentable-characters.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-emphasis-unrepresentable-characters.html new file mode 100644 index 0000000..1c108fa --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-emphasis-unrepresentable-characters.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<title>Emphasis marks for unrepresentable characters should not crash</title> +<link rel="author" title="Emil A Eklund" href="eae@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#emphasis-marks" title="3 Emphasis Marks"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> + div { + text-emphasis: circle; + -webkit-text-emphasis-style: circle; + } +</style> +<body> + <div></div> +</body> +<script> + var el = document.body.firstElementChild; + el.appendChild(document.createTextNode(unescape('%udb14'))); + el.appendChild(document.createTextNode(unescape('%udfe3%u7af4'))); +</script> +<script>test(()=>{})</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/paint/background/huge-offset-border-crash.html b/third_party/blink/web_tests/paint/background/huge-offset-border-crash.html new file mode 100644 index 0000000..bfb129f --- /dev/null +++ b/third_party/blink/web_tests/paint/background/huge-offset-border-crash.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script>test(function(){});</script> +<div style="transform: translateX(-100000000px)"> + <div style="margin-left: 100000000px"> + <div style="margin-left: 100px; width: 100px; height: 100px; + border-top: 1px solid blue; border-radius: 5px"> + </div> + </div> +</div> +
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/lock-after-append/acquire-changed-containment.html b/third_party/blink/web_tests/wpt_internal/display-lock/lock-after-append/acquire-changed-containment.html index 76474bd..c1ef658f 100644 --- a/third_party/blink/web_tests/wpt_internal/display-lock/lock-after-append/acquire-changed-containment.html +++ b/third_party/blink/web_tests/wpt_internal/display-lock/lock-after-append/acquire-changed-containment.html
@@ -4,7 +4,7 @@ <title>Display Locking: acquire, containment changes</title> <link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> <link rel="help" href="https://github.com/WICG/display-locking"> -<link rel="match" href="pass-no-containment-ref.html"> +<link rel="match" href="pass-no-containment-with-child-ref.html"> <script src="/common/reftest-wait.js"></script> <style> @@ -13,10 +13,15 @@ height: 150px; background: lightblue; } +#child { + width: 50px; + height: 50px; + background: lightgreen; +} </style> <div id="log"></div> -<div id="container" style="contain: style layout;"></div> +<div id="container" style="contain: style layout;"><div id="child" style="display: none;"></div></div> <script> function finishTest(status_string) { @@ -27,7 +32,9 @@ function runTest() { const container = document.getElementById("container"); + // Recalc child and container when acquiring. container.style = ""; + child.style = ""; container.displayLock.acquire({ timeout: Infinity }).then( () => { finishTest("FAIL"); }, (e) => { finishTest("PASS " + e.message); });
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/lock-after-append/pass-no-containment-with-child-ref.html b/third_party/blink/web_tests/wpt_internal/display-lock/lock-after-append/pass-no-containment-with-child-ref.html new file mode 100644 index 0000000..00127f4 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/display-lock/lock-after-append/pass-no-containment-with-child-ref.html
@@ -0,0 +1,24 @@ +<!doctype HTML> +<html> +<meta charset="utf8"> +<title>Display Locking: pass, container with child</title> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> +<link rel="help" href="https://github.com/WICG/display-locking"> + +<style> +#container { + contain: style layout; + width: 150px; + height: 150px; + background: lightblue; +} +#child { + width: 50px; + height: 50px; + background: lightgreen; +} +</style> + +<div id="log">PASS Containment requirement is not satisfied.</div> +<div id="container"><div id="child"></div></div> +</html>
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/lock-before-append/acquire-on-no-containment.html b/third_party/blink/web_tests/wpt_internal/display-lock/lock-before-append/acquire-on-no-containment.html new file mode 100644 index 0000000..6404357a --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/display-lock/lock-before-append/acquire-on-no-containment.html
@@ -0,0 +1,50 @@ +<!doctype HTML> +<html class="reftest-wait"> +<meta charset="utf8"> +<title>Display Locking: acquire, no containment</title> +<link rel="author" title="Rakina Zata Amni" href="mailto:rakina@chromium.org"> +<link rel="help" href="https://github.com/WICG/display-locking"> +<link rel="match" href="pass-container-with-child-ref.html"> +<script src="/common/reftest-wait.js"></script> + +<style> +#container { + width: 150px; + height: 150px; + background: lightblue; +} +#child { + width: 50px; + height: 50px; + background: lightgreen; +} +</style> + +<div id="log"></div> + +<script> +function finishTest(status_string) { + if (document.getElementById("log").innerHTML === "") + document.getElementById("log").innerHTML = status_string; + takeScreenshot(); +} + +function runTest() { + const container = document.createElement("div"); + container.id = "container"; + container.innerHTML = "<div id='child'></div>"; + container.displayLock.acquire({ timeout: Infinity }).then( + () => { + document.body.appendChild(container); + container.offsetTop; + if (container.displayLock.locked) + finishTest("FAIL didn't get unlocked"); + else + finishTest("PASS"); + }, + (e) => { finishTest("FAIL" + e.message); }); +} + +window.onload = runTest; +</script> +</html>
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium index 531e7e1..fd5e271 100644 --- a/third_party/freetype/README.chromium +++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@ Name: FreeType URL: http://www.freetype.org/ -Version: VER-2-9-1-352-g2f4b740ce -Revision: 2f4b740ce435bc1ad5ef8570bb91ab7cd5682720 +Version: VER-2-10-0-0-gfbbcf5036 +Revision: fbbcf50367403a6316a013b51690071198962920 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent JPEG Group) licenses" License File: src/docs/FTL.TXT
diff --git a/third_party/metrics_proto/README.chromium b/third_party/metrics_proto/README.chromium index 17d206c..06e3a8e 100644 --- a/third_party/metrics_proto/README.chromium +++ b/third_party/metrics_proto/README.chromium
@@ -1,8 +1,8 @@ Name: Metrics Protos Short Name: metrics_proto URL: This is the canonical public repository -Version: 249077303 -Date: 2019/05/20 UTC +Version: 249161107 +Date: 2019/05/21 UTC License: BSD Security Critical: Yes
diff --git a/third_party/metrics_proto/call_stack_profile.proto b/third_party/metrics_proto/call_stack_profile.proto index 8b001bb..e0433c4 100644 --- a/third_party/metrics_proto/call_stack_profile.proto +++ b/third_party/metrics_proto/call_stack_profile.proto
@@ -109,6 +109,13 @@ // metadata items are specified only when their values change from the // previous sample. Items are not guaranteed to be in a particular order. repeated MetadataItem metadata = 5; + + // Weight of the sample. When omitted the sample is presumed to have + // a weight of 1. + // Not currently used for CPU profiles. + // For heap profiles it represents the number of bytes attributed to the + // sample. + optional int64 weight = 6; } // The previous sample encoding. Deprecated 2018/08/04 in favor of
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index b07ac13..2e908fbe 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -19362,6 +19362,7 @@ <int value="1336" label="AUTOTESTPRIVATE_SETSHELFALIGNMENT"/> <int value="1337" label="BLUETOOTH_RECORDPAIRING"/> <int value="1338" label="FILEMANAGERPRIVATE_SETARCSTORAGETOASTSHOWNFLAG"/> + <int value="1339" label="INPUTMETHODPRIVATE_SETCOMPOSITIONRANGE"/> </enum> <enum name="ExtensionIconState"> @@ -41838,6 +41839,7 @@ <int value="3" label="Translate"/> <int value="4" label="News"/> <int value="5" label="Chrome Web Store"/> + <int value="6" label="Search"/> </enum> <enum name="NuxLandingPageInteractions"> @@ -46883,6 +46885,7 @@ <int value="4" label="Can't configure native printers due to policy"/> <int value="5" label="Invalid values are used to update printer"/> <int value="6" label="Could not install component"/> + <int value="7" label="Edit success"/> <int value="10" label="PPD exceeds size limit"/> <int value="11" label="PPD Rejected by cupstestppd"/> <int value="12" label="Could not find PPD"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index f0e659b..37f19bd 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -14671,6 +14671,9 @@ Logs when a user action triggers a command in the bookmark manager. Commands can be triggered by keyboard shortcuts, menu items or other buttons in the UI. + + Revised in M-76 when the "Open (double click/enter)" bucket was + split into two separate buckets, one for bookmarks and one for folders. </summary> </histogram> @@ -14679,6 +14682,9 @@ <owner>calamity@chromium.org</owner> <summary> Logs when a keyboard shortcut triggers a command in the bookmark manager. + + Revised in M-76 when the "Open (double click/enter)" bucket was + split into two separate buckets, one for bookmarks and one for folders. </summary> </histogram> @@ -92737,6 +92743,70 @@ </summary> </histogram> +<histogram name="Platform.Memory.ARC" units="MiB" expires_after="2020-11-01"> +<!-- Name completed by histogram_suffixes name="ProcessMemoryType" --> + + <owner>semenzato@chromium.org</owner> + <owner>sonnyrao@chromium.org</owner> + <summary> + Memory usage of all ARC processes in Chrome OS, reported every 10 minutes. + </summary> +</histogram> + +<histogram name="Platform.Memory.Browser" units="MiB" + expires_after="2020-11-01"> +<!-- Name completed by histogram_suffixes name="ProcessMemoryType" --> + + <owner>semenzato@chromium.org</owner> + <owner>sonnyrao@chromium.org</owner> + <summary> + Memory usage of browser and helper processes (excluding GPU process and + renderers) in Chrome OS, reported every 10 minutes. + </summary> +</histogram> + +<histogram name="Platform.Memory.Daemons" units="MiB" + expires_after="2020-11-01"> +<!-- Name completed by histogram_suffixes name="ProcessMemoryType" --> + + <owner>semenzato@chromium.org</owner> + <owner>sonnyrao@chromium.org</owner> + <summary> + Memory usage of user-level daemons in Chrome OS, reported every 10 minutes. + </summary> +</histogram> + +<histogram name="Platform.Memory.Gpu" units="MiB" expires_after="2020-11-01"> +<!-- Name completed by histogram_suffixes name="ProcessMemoryType" --> + + <owner>semenzato@chromium.org</owner> + <owner>sonnyrao@chromium.org</owner> + <summary> + Memory usage of the GPU process in Chrome OS, reported every 10 minutes. + </summary> +</histogram> + +<histogram name="Platform.Memory.Renderers" units="MiB" + expires_after="2020-11-01"> +<!-- Name completed by histogram_suffixes name="ProcessMemoryType" --> + + <owner>semenzato@chromium.org</owner> + <owner>sonnyrao@chromium.org</owner> + <summary> + Memory usage of renderer processes in Chrome OS, reported every 10 minutes. + </summary> +</histogram> + +<histogram name="Platform.Memory.VMs" units="MiB" expires_after="2020-11-01"> +<!-- Name completed by histogram_suffixes name="ProcessMemoryType" --> + + <owner>semenzato@chromium.org</owner> + <owner>sonnyrao@chromium.org</owner> + <summary> + Memory usage of VMs (crostini) in Chrome OS, reported every 10 minutes. + </summary> +</histogram> + <histogram name="Platform.MemoryBandwidth.ReadWrite" units="MB/s"> <owner>hajimehoshi@chromium.org</owner> <owner>kouhei@chromium.org</owner> @@ -155638,6 +155708,20 @@ <affected-histogram name="Memory.Experimental.Utility2.Small"/> </histogram_suffixes> +<histogram_suffixes name="ProcessMemoryType" separator="."> + <suffix name="Anon" label="Measures anonymous RSS."/> + <suffix name="File" label="Measures file RSS."/> + <suffix name="Shmem" label="Measures shmem RSS."/> + <suffix name="Swap" label="Measures swap in use."/> + <suffix name="Total" label="Measures total RSS."/> + <affected-histogram name="Platform.Memory.ARC"/> + <affected-histogram name="Platform.Memory.Browser"/> + <affected-histogram name="Platform.Memory.Daemons"/> + <affected-histogram name="Platform.Memory.Gpu"/> + <affected-histogram name="Platform.Memory.Renderers"/> + <affected-histogram name="Platform.Memory.VMs"/> +</histogram_suffixes> + <histogram_suffixes name="ProcessType" separator="."> <obsolete> Removed 2019-05
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index bd13b26..a9e8e21e 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -157,6 +157,7 @@ <item id="network_location_request" hash_code="96590038" type="2" content_hash_code="80741011" os_list="linux,windows" semantics_fields="2,3,4,5" policy_fields="-1" file_path="services/device/geolocation/network_location_request.cc"/> <item id="network_time_component" hash_code="46188932" type="0" content_hash_code="28051857" os_list="linux,windows" file_path="components/network_time/network_time_tracker.cc"/> <item id="ntp_contextual_suggestions_fetch" hash_code="95711309" type="0" deprecated="2019-04-18" content_hash_code="107035434" file_path=""/> + <item id="ntp_custom_background" hash_code="92125886" type="0" content_hash_code="61176452" os_list="linux,windows" file_path="chrome/browser/search/instant_service.cc"/> <item id="ntp_custom_link_checker_request" hash_code="78408551" type="0" deprecated="2018-10-26" content_hash_code="13407730" file_path=""/> <item id="ntp_icon_source" hash_code="29197139" type="0" content_hash_code="16399294" os_list="linux,windows" file_path="chrome/browser/search/ntp_icon_source.cc"/> <item id="ntp_snippets_fetch" hash_code="15418154" type="0" content_hash_code="10078959" os_list="linux,windows" file_path="components/ntp_snippets/remote/json_request.cc"/>
diff --git a/ui/accessibility/ax_event_generator.h b/ui/accessibility/ax_event_generator.h index 1f80d95e..44f62aa 100644 --- a/ui/accessibility/ax_event_generator.h +++ b/ui/accessibility/ax_event_generator.h
@@ -231,7 +231,7 @@ std::vector<AXNode*> active_descendant_changed_; // The value of the event from field in TargetedEvent. - ax::mojom::EventFrom event_from_; + ax::mojom::EventFrom event_from_ = ax::mojom::EventFrom::kNone; }; } // namespace ui
diff --git a/ui/accessibility/ax_node_position_unittest.cc b/ui/accessibility/ax_node_position_unittest.cc index 368a5f8..02738ff3 100644 --- a/ui/accessibility/ax_node_position_unittest.cc +++ b/ui/accessibility/ax_node_position_unittest.cc
@@ -2508,6 +2508,8 @@ "affinity=downstream annotated_text=Line 1\n<L>ine 2", "TextPosition anchor_id=1 text_offset=12 " "affinity=downstream annotated_text=Line 1\nLine <2>", + "TextPosition anchor_id=1 text_offset=13 " + "affinity=downstream annotated_text=Line 1\nLine 2<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreateNextWordStartPosition( @@ -2521,6 +2523,8 @@ "affinity=downstream annotated_text=Line 1\n<L>ine 2", "TextPosition anchor_id=4 text_offset=12 " "affinity=downstream annotated_text=Line 1\nLine <2>", + "TextPosition anchor_id=4 text_offset=13 " + "affinity=downstream annotated_text=Line 1\nLine 2<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreateNextWordStartPosition( @@ -2534,6 +2538,8 @@ "affinity=downstream annotated_text=<L>ine 2", "TextPosition anchor_id=9 text_offset=5 " "affinity=downstream annotated_text=Line <2>", + "TextPosition anchor_id=9 text_offset=6 " + "affinity=downstream annotated_text=Line 2<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreateNextWordStartPosition( @@ -2543,6 +2549,8 @@ 4 /* text_offset */, {"TextPosition anchor_id=9 text_offset=5 " "affinity=downstream annotated_text=Line <2>", + "TextPosition anchor_id=9 text_offset=6 " + "affinity=downstream annotated_text=Line 2<>", "NullPosition"}})); INSTANTIATE_TEST_SUITE_P( @@ -2977,6 +2985,8 @@ "affinity=downstream annotated_text=Line 1<\n>Line 2", "TextPosition anchor_id=1 text_offset=4 " "affinity=downstream annotated_text=Line< >1\nLine 2", + "TextPosition anchor_id=1 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousWordEndPosition( @@ -2990,6 +3000,8 @@ "affinity=downstream annotated_text=Line 1<\n>Line 2", "TextPosition anchor_id=4 text_offset=4 " "affinity=downstream annotated_text=Line< >1\nLine 2", + "TextPosition anchor_id=4 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousWordEndPosition( @@ -2999,6 +3011,8 @@ 5 /* text_offset */, {"TextPosition anchor_id=5 text_offset=4 " "affinity=downstream annotated_text=Line< >1", + "TextPosition anchor_id=5 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousWordEndPosition( @@ -3010,6 +3024,8 @@ "affinity=downstream annotated_text=Line 1<>", "TextPosition anchor_id=6 text_offset=4 " "affinity=downstream annotated_text=Line< >1", + "TextPosition anchor_id=6 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1", "NullPosition"}})); INSTANTIATE_TEST_SUITE_P( @@ -3116,6 +3132,8 @@ 0 /* text_offset */, {"TextPosition anchor_id=1 text_offset=7 " "affinity=downstream annotated_text=Line 1\n<L>ine 2", + "TextPosition anchor_id=1 text_offset=13 " + "affinity=downstream annotated_text=Line 1\nLine 2<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreateNextLineStartPosition( @@ -3125,6 +3143,8 @@ 0 /* text_offset */, {"TextPosition anchor_id=4 text_offset=7 " "affinity=downstream annotated_text=Line 1\n<L>ine 2", + "TextPosition anchor_id=4 text_offset=13 " + "affinity=downstream annotated_text=Line 1\nLine 2<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreateNextLineStartPosition( @@ -3134,6 +3154,8 @@ 1 /* text_offset */, {"TextPosition anchor_id=9 text_offset=0 " "affinity=downstream annotated_text=<L>ine 2", + "TextPosition anchor_id=9 text_offset=6 " + "affinity=downstream annotated_text=Line 2<>", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreateNextLineStartPosition( @@ -3141,7 +3163,9 @@ }), INLINE_BOX2_ID, 4 /* text_offset */, - {"NullPosition"}})); + {"TextPosition anchor_id=9 text_offset=6 " + "affinity=downstream annotated_text=Line 2<>", + "NullPosition"}})); INSTANTIATE_TEST_SUITE_P( CreateNextLineStartPositionWithBoundaryBehaviorStopAtAnchorBoundary, @@ -3224,7 +3248,10 @@ }), INLINE_BOX2_ID, 4 /* text_offset */, - {"NullPosition"}})); + {"TextPosition anchor_id=9 text_offset=6 affinity=downstream " + "annotated_text=Line 2<>", + "TextPosition anchor_id=9 text_offset=6 affinity=downstream " + "annotated_text=Line 2<>"}})); INSTANTIATE_TEST_SUITE_P( CreatePreviousLineStartPositionWithBoundaryBehaviorCrossBoundary, @@ -3520,6 +3547,8 @@ 13 /* text_offset at end of root. */, {"TextPosition anchor_id=1 text_offset=6 " "affinity=downstream annotated_text=Line 1<\n>Line 2", + "TextPosition anchor_id=1 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineEndPosition( @@ -3529,6 +3558,8 @@ 13 /* text_offset at end of text field */, {"TextPosition anchor_id=4 text_offset=6 " "affinity=downstream annotated_text=Line 1<\n>Line 2", + "TextPosition anchor_id=4 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineEndPosition( @@ -3536,14 +3567,18 @@ }), ROOT_ID, 5 /* text_offset on the last character of "Line 1". */, - {"NullPosition"}}, + {"TextPosition anchor_id=1 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2", + "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineEndPosition( AXBoundaryBehavior::CrossBoundary); }), TEXT_FIELD_ID, 5 /* text_offset on the last character of "Line 1". */, - {"NullPosition"}}, + {"TextPosition anchor_id=4 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1\nLine 2", + "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineEndPosition( AXBoundaryBehavior::CrossBoundary); @@ -3552,6 +3587,8 @@ 4 /* text_offset */, {"TextPosition anchor_id=6 text_offset=6 " "affinity=downstream annotated_text=Line 1<>", + "TextPosition anchor_id=6 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1", "NullPosition"}}, TestParam{base::BindRepeating([](const TestPositionType& position) { return position->CreatePreviousLineEndPosition( @@ -3561,6 +3598,8 @@ 0 /* text_offset */, {"TextPosition anchor_id=6 text_offset=6 " "affinity=downstream annotated_text=Line 1<>", + "TextPosition anchor_id=6 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1", "NullPosition"}})); INSTANTIATE_TEST_SUITE_P( @@ -3660,6 +3699,16 @@ return position->CreatePreviousLineEndPosition( AXBoundaryBehavior::StopIfAlreadyAtBoundary); }), + INLINE_BOX1_ID, + 2 /* text_offset */, + {"TextPosition anchor_id=6 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1", + "TextPosition anchor_id=6 text_offset=0 " + "affinity=downstream annotated_text=<L>ine 1"}}, + TestParam{base::BindRepeating([](const TestPositionType& position) { + return position->CreatePreviousLineEndPosition( + AXBoundaryBehavior::StopIfAlreadyAtBoundary); + }), INLINE_BOX2_ID, 4 /* text_offset */, {"TextPosition anchor_id=6 text_offset=6 "
diff --git a/ui/accessibility/ax_position.h b/ui/accessibility/ax_position.h index 0e03689d..56c9c30 100644 --- a/ui/accessibility/ax_position.h +++ b/ui/accessibility/ax_position.h
@@ -904,9 +904,10 @@ do { text_position = text_position->CreateNextTextAnchorPosition(); if (text_position->IsNullPosition()) { - if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) - return CreatePositionAtEndOfAnchor(); - return text_position; + if (AtEndOfAnchor() && + boundary_behavior == AXBoundaryBehavior::CrossBoundary) + return text_position; + return CreatePositionAtEndOfAnchor(); } } while (!text_position->MaxTextOffset() || text_position->GetWordStartOffsets().empty()); @@ -1104,9 +1105,10 @@ text_position = text_position->CreatePreviousTextAnchorPosition() ->CreatePositionAtEndOfAnchor(); if (text_position->IsNullPosition()) { - if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) - return CreatePositionAtStartOfAnchor(); - return text_position; + if (AtStartOfAnchor() && + boundary_behavior == AXBoundaryBehavior::CrossBoundary) + return text_position; + return CreatePositionAtStartOfAnchor(); } } while (!text_position->MaxTextOffset() || text_position->GetWordStartOffsets().empty()); @@ -1160,9 +1162,10 @@ do { text_position = text_position->CreateNextTextAnchorPosition(); if (text_position->IsNullPosition()) { - if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) - return CreatePositionAtEndOfAnchor(); - return text_position; + if (AtEndOfAnchor() && + boundary_behavior == AXBoundaryBehavior::CrossBoundary) + return text_position; + return CreatePositionAtEndOfAnchor(); } // Continue searching for the next line start until the next logical text @@ -1319,9 +1322,10 @@ text_position = text_position->CreatePreviousTextAnchorPosition() ->CreatePositionAtEndOfAnchor(); if (text_position->IsNullPosition()) { - if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) - return CreatePositionAtStartOfAnchor(); - return text_position; + if (AtStartOfAnchor() && + boundary_behavior == AXBoundaryBehavior::CrossBoundary) + return text_position; + return CreatePositionAtStartOfAnchor(); } // Continue searching for the previous line end until the next logical
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc index fc30f378..18fcd9b 100644 --- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc +++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
@@ -379,6 +379,10 @@ if (attribute_value_variant.type() == VT_EMPTY) { attribute_value_variant.Reset(current_variant); + if (attribute_value_variant.type() == VT_UNKNOWN) { + *value = attribute_value_variant.Release(); + return S_OK; + } } else if (0 != attribute_value_variant.Compare(current_variant)) { V_VT(value) = VT_UNKNOWN; return ::UiaGetReservedMixedAttributeValue(&V_UNKNOWN(value)); @@ -509,16 +513,30 @@ HRESULT hr = MoveEndpointByUnit(TextPatternRangeEndpoint_Start, unit, count, &start_units_moved); - bool succeeded_move = SUCCEEDED(hr) && start_units_moved == count; + bool succeeded_move = SUCCEEDED(hr) && start_units_moved != 0; if (succeeded_move) { end_ = start_->Clone(); if (!is_degenerate_range) { - // Expand the text range from the degenerate state by moving the - // endpoint forward by one text unit. - int end_units_moved = 0; - hr = MoveEndpointByUnit(TextPatternRangeEndpoint_End, unit, 1, - &end_units_moved); - succeeded_move = SUCCEEDED(hr) && end_units_moved == 1; + bool forwards = count > 0; + if (forwards && start_->AtEndOfDocument()) { + // The start is at the end of the document, so move the start backward + // by one text unit to expand the text range from the degenerate range + // state. + int current_start_units_moved = 0; + hr = MoveEndpointByUnit(TextPatternRangeEndpoint_Start, unit, -1, + ¤t_start_units_moved); + start_units_moved -= 1; + succeeded_move = SUCCEEDED(hr) && current_start_units_moved == -1 && + start_units_moved > 0; + } else { + // The start is not at the end of the document, so move the endpoint + // forward by one text unit to expand the text range from the degenerate + // state. + int end_units_moved = 0; + hr = MoveEndpointByUnit(TextPatternRangeEndpoint_End, unit, 1, + &end_units_moved); + succeeded_move = SUCCEEDED(hr) && end_units_moved == 1; + } } }
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc index f4264d9..c84e45dd 100644 --- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc +++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc
@@ -90,6 +90,30 @@ EXPECT_EQ(0, scoped_variant.Compare(variant)); \ } +#define EXPECT_UIA_TEXTATTRIBUTE_MIXED(provider, attribute) \ + { \ + CComPtr<IUnknown> expected_mixed; \ + EXPECT_HRESULT_SUCCEEDED( \ + ::UiaGetReservedMixedAttributeValue(&expected_mixed)); \ + base::win::ScopedVariant scoped_variant; \ + EXPECT_HRESULT_SUCCEEDED( \ + provider->GetAttributeValue(attribute, scoped_variant.Receive())); \ + EXPECT_EQ(VT_UNKNOWN, scoped_variant.type()); \ + EXPECT_EQ(expected_mixed, V_UNKNOWN(scoped_variant.ptr())); \ + } + +#define EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(provider, attribute) \ + { \ + CComPtr<IUnknown> expected_notsupported; \ + EXPECT_HRESULT_SUCCEEDED( \ + ::UiaGetReservedNotSupportedValue(&expected_notsupported)); \ + base::win::ScopedVariant scoped_variant; \ + EXPECT_HRESULT_SUCCEEDED( \ + provider->GetAttributeValue(attribute, scoped_variant.Receive())); \ + EXPECT_EQ(VT_UNKNOWN, scoped_variant.type()); \ + EXPECT_EQ(expected_notsupported, V_UNKNOWN(scoped_variant.ptr())); \ + } + #define EXPECT_UIA_TEXTRANGE_EQ(provider, expected_content) \ { \ base::win::ScopedBstr provider_content; \ @@ -1133,7 +1157,7 @@ /*expected_text*/ L"b", /*expected_count*/ 16); EXPECT_UIA_MOVE(text_range_provider, TextUnit_Character, - /*count*/ 30, + /*count*/ 60, /*expected_text*/ L"2", /*expected_count*/ 30); @@ -1153,7 +1177,7 @@ /*expected_text*/ L"1", /*expected_count*/ -9); EXPECT_UIA_MOVE(text_range_provider, TextUnit_Character, - /*count*/ -54, + /*count*/ -60, /*expected_text*/ L"F", /*expected_count*/ -54); @@ -1175,6 +1199,10 @@ /*count*/ 4, /*expected_text*/ L"", /*expected_count*/ 4); + EXPECT_UIA_MOVE(text_range_provider, TextUnit_Character, + /*count*/ 70, + /*expected_text*/ L"", + /*expected_count*/ 62); // Trying to move past the last character should have no effect. EXPECT_UIA_MOVE(text_range_provider, TextUnit_Character, @@ -1303,6 +1331,10 @@ /*count*/ 3, /*expected_text*/ L"", /*expected_count*/ 3); + EXPECT_UIA_MOVE(text_range_provider, TextUnit_Format, + /*count*/ 70, + /*expected_text*/ L"", + /*expected_count*/ 3); // Trying to move past the last format should have no effect. EXPECT_UIA_MOVE(text_range_provider, TextUnit_Format, @@ -1351,7 +1383,7 @@ /*expected_text*/ L"Paragraph", /*expected_count*/ 3); EXPECT_UIA_MOVE(text_range_provider, TextUnit_Word, - /*count*/ 3, + /*count*/ 6, /*expected_text*/ L"2", /*expected_count*/ 3); @@ -1375,7 +1407,7 @@ /*expected_text*/ L"text", /*expected_count*/ -2); EXPECT_UIA_MOVE(text_range_provider, TextUnit_Word, - /*count*/ -3, + /*count*/ -6, /*expected_text*/ L"First", /*expected_count*/ -3); @@ -1387,15 +1419,19 @@ /*expected_count*/ 0); // Degenerate range moves. - EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT( - text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Document, - /*count*/ -1, - /*expected_text*/ L"", - /*expected_count*/ -1); + EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(text_range_provider, + TextPatternRangeEndpoint_End, TextUnit_Word, + /*count*/ -1, + /*expected_text*/ L"", + /*expected_count*/ -1); EXPECT_UIA_MOVE(text_range_provider, TextUnit_Word, /*count*/ 4, /*expected_text*/ L"", /*expected_count*/ 4); + EXPECT_UIA_MOVE(text_range_provider, TextUnit_Word, + /*count*/ 70, + /*expected_text*/ L"", + /*expected_count*/ 8); // Trying to move past the last word should have no effect. EXPECT_UIA_MOVE(text_range_provider, TextUnit_Word, @@ -1436,7 +1472,7 @@ /*expected_text*/ L"bold text", /*expected_count*/ 1); EXPECT_UIA_MOVE(text_range_provider, TextUnit_Line, - /*count*/ 2, + /*count*/ 10, /*expected_text*/ L"Paragraph 2", /*expected_count*/ 2); @@ -1452,7 +1488,7 @@ /*expected_text*/ L"Paragraph 1", /*expected_count*/ -1); EXPECT_UIA_MOVE(text_range_provider, TextUnit_Line, - /*count*/ -4, + /*count*/ -5, /*expected_text*/ L"First line of text", /*expected_count*/ -4); @@ -1464,15 +1500,19 @@ /*expected_count*/ 0); // Degenerate range moves. - EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT( - text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Document, - /*count*/ -1, - /*expected_text*/ L"", - /*expected_count*/ -1); + EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(text_range_provider, + TextPatternRangeEndpoint_End, TextUnit_Line, + /*count*/ -1, + /*expected_text*/ L"", + /*expected_count*/ -1); EXPECT_UIA_MOVE(text_range_provider, TextUnit_Line, /*count*/ 4, /*expected_text*/ L"", /*expected_count*/ 4); + EXPECT_UIA_MOVE(text_range_provider, TextUnit_Line, + /*count*/ 70, + /*expected_text*/ L"", + /*expected_count*/ 2); // Trying to move past the last line should have no effect. EXPECT_UIA_MOVE(text_range_provider, TextUnit_Line, @@ -1551,21 +1591,21 @@ EXPECT_UIA_MOVE(text_range_provider, TextUnit_Page, /*count*/ 4, /*expected_text*/ L"", - /*expected_count*/ 0); + /*expected_count*/ 1); // Trying to move past the last character should have no effect. EXPECT_UIA_MOVE(text_range_provider, TextUnit_Document, /*count*/ 1, /*expected_text*/ L"", - /*expected_count*/ 1); + /*expected_count*/ 0); EXPECT_UIA_MOVE(text_range_provider, TextUnit_Page, /*count*/ -2, /*expected_text*/ L"", - /*expected_count*/ 0); + /*expected_count*/ -1); EXPECT_UIA_MOVE(text_range_provider, TextUnit_Document, /*count*/ -1, /*expected_text*/ L"", - /*expected_count*/ -1); + /*expected_count*/ 0); AXNodePosition::SetTreeForTesting(nullptr); } @@ -1839,18 +1879,18 @@ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT( text_range_provider, TextPatternRangeEndpoint_Start, TextUnit_Word, /*count*/ 6, - /*expected_text*/ L"text", - /*expected_count*/ 4); + /*expected_text*/ L"", + /*expected_count*/ 5); EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT( text_range_provider, TextPatternRangeEndpoint_Start, TextUnit_Word, - /*count*/ -7, + /*count*/ -8, /*expected_text*/ L"some textmore texteven more text", - /*expected_count*/ -6); + /*expected_count*/ -7); EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Word, /*count*/ -8, - /*expected_text*/ L"some", - /*expected_count*/ -6); + /*expected_text*/ L"", + /*expected_count*/ -7); } TEST_F(AXPlatformNodeTextRangeProviderTest, @@ -1920,23 +1960,23 @@ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Line, /*count*/ -13, - /*expected_text*/ L"0", - /*expected_count*/ -5); + /*expected_text*/ L"", + /*expected_count*/ -6); EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Line, /*count*/ 11, /*expected_text*/ L"0123456", - /*expected_count*/ 6); + /*expected_count*/ 7); EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT( text_range_provider, TextPatternRangeEndpoint_Start, TextUnit_Line, /*count*/ 9, - /*expected_text*/ L"6", - /*expected_count*/ 6); + /*expected_text*/ L"", + /*expected_count*/ 7); EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT( text_range_provider, TextPatternRangeEndpoint_Start, TextUnit_Line, /*count*/ -7, /*expected_text*/ L"0123456", - /*expected_count*/ -6); + /*expected_count*/ -7); } // Verify that the endpoint can move past an empty text field. @@ -2751,15 +2791,6 @@ GetTextRangeProviderFromTextNode(list_item2_text_range_provider, list_item2_text_node); - base::win::ScopedVariant expected_mixed_variant; - { - VARIANT var; - V_VT(&var) = VT_UNKNOWN; - EXPECT_HRESULT_SUCCEEDED( - ::UiaGetReservedMixedAttributeValue(&V_UNKNOWN(&var))); - expected_mixed_variant.Reset(var); - } - base::win::ScopedVariant expected_variant; // SkColor is ARGB, COLORREF is 0BGR @@ -2822,8 +2853,8 @@ expected_variant); expected_variant.Reset(); - EXPECT_UIA_TEXTATTRIBUTE_EQ(document_range_provider, UIA_IsHiddenAttributeId, - expected_mixed_variant); + EXPECT_UIA_TEXTATTRIBUTE_MIXED(document_range_provider, + UIA_IsHiddenAttributeId); expected_variant.Set(true); EXPECT_UIA_TEXTATTRIBUTE_EQ(text_range_provider, UIA_IsItalicAttributeId, @@ -2911,12 +2942,97 @@ static_cast<int32_t>(FlowDirections::FlowDirections_RightToLeft)); EXPECT_UIA_TEXTATTRIBUTE_EQ( text_range_provider, UIA_TextFlowDirectionsAttributeId, expected_variant); - EXPECT_UIA_TEXTATTRIBUTE_EQ(document_range_provider, - UIA_TextFlowDirectionsAttributeId, - expected_variant); + EXPECT_UIA_TEXTATTRIBUTE_MIXED(document_range_provider, + UIA_TextFlowDirectionsAttributeId); expected_variant.Reset(); } +TEST_F(AXPlatformNodeTextRangeProviderTest, + TestITextRangeProviderGetAttributeValueNotSupported) { + ui::AXNodeData root_data; + root_data.id = 0; + root_data.role = ax::mojom::Role::kRootWebArea; + root_data.child_ids = {1, 2}; + + ui::AXNodeData text_data_first; + text_data_first.id = 1; + text_data_first.role = ax::mojom::Role::kStaticText; + text_data_first.SetName("first"); + + ui::AXNodeData text_data_second; + text_data_second.id = 2; + text_data_second.role = ax::mojom::Role::kStaticText; + text_data_second.SetName("second"); + + ui::AXTreeUpdate update; + ui::AXTreeData tree_data; + tree_data.tree_id = ui::AXTreeID::CreateNewAXTreeID(); + update.tree_data = tree_data; + update.has_tree_data = true; + update.root_id = root_data.id; + update.nodes.push_back(root_data); + update.nodes.push_back(text_data_first); + update.nodes.push_back(text_data_second); + + Init(update); + AXNodePosition::SetTreeForTesting(tree_.get()); + AXTreeManagerMap::GetInstance().AddTreeManager(tree_data.tree_id, this); + + ComPtr<ITextRangeProvider> document_range_provider; + GetTextRangeProviderFromTextNode(document_range_provider, GetRootNode()); + + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_AfterParagraphSpacingAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_AnimationStyleAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_AnnotationObjectsAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_AnnotationTypesAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_BeforeParagraphSpacingAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_CapStyleAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_CaretBidiModeAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_CaretPositionAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_HorizontalTextAlignmentAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_IndentationFirstLineAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_IndentationLeadingAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_IndentationTrailingAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_IsActiveAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_LineSpacingAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_LinkAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_MarginBottomAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_MarginLeadingAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_MarginTopAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_MarginTrailingAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_OutlineStylesAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_OverlineColorAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_SelectionActiveEndAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_StrikethroughColorAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_TabsAttributeId); + EXPECT_UIA_TEXTATTRIBUTE_NOTSUPPORTED(document_range_provider, + UIA_UnderlineColorAttributeId); +} + TEST_F(AXPlatformNodeTextRangeProviderTest, TestITextRangeProviderSelect) { Init(BuildTextDocument({"some text", "more text2"})); AXNodePosition::SetTreeForTesting(tree_.get());
diff --git a/ui/accessibility/platform/ax_platform_node_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_win_unittest.cc index 42e099c9..16c9818 100644 --- a/ui/accessibility/platform/ax_platform_node_win_unittest.cc +++ b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
@@ -1135,23 +1135,32 @@ // Logical directions should be supported. EXPECT_EQ(S_OK, ia_root->accNavigate(NAVDIR_FIRSTCHILD, SELF, end.AsInput())); - EXPECT_EQ(0, var_child1.Compare(end)); + EXPECT_EQ(VT_DISPATCH, end.type()); + EXPECT_EQ(V_DISPATCH(var_child1.ptr()), V_DISPATCH(end.ptr())); + EXPECT_EQ(S_OK, ia_root->accNavigate(NAVDIR_LASTCHILD, SELF, end.AsInput())); - EXPECT_EQ(0, var_child2.Compare(end)); + EXPECT_EQ(VT_DISPATCH, end.type()); + EXPECT_EQ(V_DISPATCH(var_child2.ptr()), V_DISPATCH(end.ptr())); EXPECT_EQ(S_OK, ia_child1->accNavigate(NAVDIR_NEXT, SELF, end.AsInput())); - EXPECT_EQ(0, var_child2.Compare(end)); + EXPECT_EQ(VT_DISPATCH, end.type()); + EXPECT_EQ(V_DISPATCH(var_child2.ptr()), V_DISPATCH(end.ptr())); + EXPECT_EQ(S_OK, ia_child2->accNavigate(NAVDIR_PREVIOUS, SELF, end.AsInput())); - EXPECT_EQ(0, var_child1.Compare(end)); + EXPECT_EQ(VT_DISPATCH, end.type()); + EXPECT_EQ(V_DISPATCH(var_child1.ptr()), V_DISPATCH(end.ptr())); // Child indices can also be passed by variant. // Indices are one-based. EXPECT_EQ(S_OK, ia_root->accNavigate(NAVDIR_NEXT, ScopedVariant(1), end.AsInput())); - EXPECT_EQ(0, var_child2.Compare(end)); + EXPECT_EQ(VT_DISPATCH, end.type()); + EXPECT_EQ(V_DISPATCH(var_child2.ptr()), V_DISPATCH(end.ptr())); + EXPECT_EQ(S_OK, ia_root->accNavigate(NAVDIR_PREVIOUS, ScopedVariant(2), end.AsInput())); - EXPECT_EQ(0, var_child1.Compare(end)); + EXPECT_EQ(VT_DISPATCH, end.type()); + EXPECT_EQ(V_DISPATCH(var_child1.ptr()), V_DISPATCH(end.ptr())); // Test out-of-bounds. EXPECT_EQ(S_FALSE,
diff --git a/ui/aura/env.cc b/ui/aura/env.cc index b090310d..d7b077d 100644 --- a/ui/aura/env.cc +++ b/ui/aura/env.cc
@@ -9,7 +9,6 @@ #include "base/memory/ptr_util.h" #include "base/observer_list_types.h" #include "components/viz/common/features.h" -#include "services/ws/public/mojom/window_tree.mojom.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/env_input_state_controller.h" #include "ui/aura/env_observer.h"
diff --git a/ui/base/ime/chromeos/input_method_chromeos.cc b/ui/base/ime/chromeos/input_method_chromeos.cc index c8daab1..7a9b966 100644 --- a/ui/base/ime/chromeos/input_method_chromeos.cc +++ b/ui/base/ime/chromeos/input_method_chromeos.cc
@@ -151,6 +151,17 @@ } } +InputMethodChromeOS::PendingSetCompositionRange::PendingSetCompositionRange( + const gfx::Range& range, + const std::vector<ui::ImeTextSpan>& text_spans) + : range(range), text_spans(text_spans) {} + +InputMethodChromeOS::PendingSetCompositionRange::PendingSetCompositionRange( + const PendingSetCompositionRange& other) = default; + +InputMethodChromeOS::PendingSetCompositionRange::~PendingSetCompositionRange() = + default; + void InputMethodChromeOS::DispatchKeyEventAsync(ui::KeyEvent* event, AckCallback ack_callback) { ignore_result(DispatchKeyEventInternal(event, std::move(ack_callback))); @@ -466,6 +477,34 @@ OnCaretBoundsChanged(GetTextInputClient()); } +bool InputMethodChromeOS::SetCompositionRange( + uint32_t before, + uint32_t after, + const std::vector<ui::ImeTextSpan>& text_spans) { + if (IsTextInputTypeNone()) + return false; + + // The given range and spans are relative to the current selection. + gfx::Range range; + if (!GetTextInputClient()->GetEditableSelectionRange(&range)) + return false; + + const gfx::Range composition_range(range.start() - before, + range.end() + after); + + // If we have pending key events, then delay the operation until + // |ProcessKeyEventPostIME|. Otherwise, process it immediately. + if (handling_key_event_) { + composition_changed_ = true; + pending_composition_range_ = + PendingSetCompositionRange{composition_range, text_spans}; + return true; + } else { + return GetTextInputClient()->SetCompositionFromExistingText( + composition_range, text_spans); + } +} + void InputMethodChromeOS::ConfirmCompositionText() { TextInputClient* client = GetTextInputClient(); if (client && client->HasCompositionText()) @@ -673,13 +712,22 @@ } } + // TODO(https://crbug.com/952757): Refactor this code to be clearer and less + // error-prone. if (composition_changed_ && !IsTextInputTypeNone()) { + if (pending_composition_range_) { + client->SetCompositionFromExistingText( + pending_composition_range_->range, + pending_composition_range_->text_spans); + } if (composition_.text.length()) { composing_text_ = true; client->SetCompositionText(composition_); - } else if (result_text_.empty()) { + } else if (result_text_.empty() && !pending_composition_range_) { client->ClearCompositionText(); } + + pending_composition_range_.reset(); } // We should not clear composition text here, as it may belong to the next
diff --git a/ui/base/ime/chromeos/input_method_chromeos.h b/ui/base/ime/chromeos/input_method_chromeos.h index 41d809e..da5714f 100644 --- a/ui/base/ime/chromeos/input_method_chromeos.h +++ b/ui/base/ime/chromeos/input_method_chromeos.h
@@ -56,6 +56,10 @@ TextInputClient* focused) override; void OnDidChangeFocusedClient(TextInputClient* focused_before, TextInputClient* focused) override; + bool SetCompositionRange( + uint32_t before, + uint32_t after, + const std::vector<ui::ImeTextSpan>& text_spans) override; protected: // Converts |text| into CompositionText. @@ -79,6 +83,17 @@ class PendingKeyEvent; friend TestableInputMethodChromeOS; + // Representings a pending SetCompositionRange operation. + struct PendingSetCompositionRange { + PendingSetCompositionRange(const gfx::Range& range, + const std::vector<ui::ImeTextSpan>& text_spans); + PendingSetCompositionRange(const PendingSetCompositionRange& other); + ~PendingSetCompositionRange(); + + gfx::Range range; + std::vector<ui::ImeTextSpan> text_spans; + }; + ui::EventDispatchDetails DispatchKeyEventInternal(ui::KeyEvent* event, AckCallback ack_callback); @@ -178,6 +193,9 @@ // Indicates if the composition text is changed or deleted. bool composition_changed_; + // Indicates whether there is a pending SetCompositionRange operation. + base::Optional<PendingSetCompositionRange> pending_composition_range_; + // An object to compose a character from a sequence of key presses // including dead key etc. CharacterComposer character_composer_;
diff --git a/ui/base/ime/ime_input_context_handler_interface.h b/ui/base/ime/ime_input_context_handler_interface.h index 21c0f45c5..88abe7dd 100644 --- a/ui/base/ime/ime_input_context_handler_interface.h +++ b/ui/base/ime/ime_input_context_handler_interface.h
@@ -25,6 +25,15 @@ // Called when the engine commit a text. virtual void CommitText(const std::string& text) = 0; +#if defined(OS_CHROMEOS) + // Called when the engine changes the composition range. + // Returns whether the operation was successful. + virtual bool SetCompositionRange( + uint32_t before, + uint32_t after, + const std::vector<ui::ImeTextSpan>& text_spans) = 0; +#endif + // Called when the engine updates composition text. virtual void UpdateCompositionText(const CompositionText& text, uint32_t cursor_pos,
diff --git a/ui/base/ime/input_method_base.cc b/ui/base/ime/input_method_base.cc index b2203feb..b621ced 100644 --- a/ui/base/ime/input_method_base.cc +++ b/ui/base/ime/input_method_base.cc
@@ -254,6 +254,15 @@ SendFakeProcessKeyEvent(false); } +#if defined(OS_CHROMEOS) +bool InputMethodBase::SetCompositionRange( + uint32_t before, + uint32_t after, + const std::vector<ui::ImeTextSpan>& text_spans) { + return false; +} +#endif + void InputMethodBase::DeleteSurroundingText(int32_t offset, uint32_t length) {} SurroundingTextInfo InputMethodBase::GetSurroundingTextInfo() {
diff --git a/ui/base/ime/input_method_base.h b/ui/base/ime/input_method_base.h index be649f4..fb57c53 100644 --- a/ui/base/ime/input_method_base.h +++ b/ui/base/ime/input_method_base.h
@@ -90,6 +90,14 @@ void UpdateCompositionText(const CompositionText& text, uint32_t cursor_pos, bool visible) override; + +#if defined(OS_CHROMEOS) + bool SetCompositionRange( + uint32_t before, + uint32_t after, + const std::vector<ui::ImeTextSpan>& text_spans) override; +#endif + void DeleteSurroundingText(int32_t offset, uint32_t length) override; SurroundingTextInfo GetSurroundingTextInfo() override; void SendKeyEvent(KeyEvent* event) override;
diff --git a/ui/base/ime/mock_ime_input_context_handler.cc b/ui/base/ime/mock_ime_input_context_handler.cc index e01c87e..fdb9a392 100644 --- a/ui/base/ime/mock_ime_input_context_handler.cc +++ b/ui/base/ime/mock_ime_input_context_handler.cc
@@ -32,6 +32,15 @@ last_update_composition_arg_.is_visible = visible; } +#if defined(OS_CHROMEOS) +bool MockIMEInputContextHandler::SetCompositionRange( + uint32_t before, + uint32_t after, + const std::vector<ui::ImeTextSpan>& text_spans) { + return false; +} +#endif + void MockIMEInputContextHandler::DeleteSurroundingText(int32_t offset, uint32_t length) { ++delete_surrounding_text_call_count_;
diff --git a/ui/base/ime/mock_ime_input_context_handler.h b/ui/base/ime/mock_ime_input_context_handler.h index 2d0df39..9e66f32 100644 --- a/ui/base/ime/mock_ime_input_context_handler.h +++ b/ui/base/ime/mock_ime_input_context_handler.h
@@ -36,6 +36,14 @@ void UpdateCompositionText(const CompositionText& text, uint32_t cursor_pos, bool visible) override; + +#if defined(OS_CHROMEOS) + bool SetCompositionRange( + uint32_t before, + uint32_t after, + const std::vector<ui::ImeTextSpan>& text_spans) override; +#endif + void DeleteSurroundingText(int32_t offset, uint32_t length) override; SurroundingTextInfo GetSurroundingTextInfo() override; void SendKeyEvent(KeyEvent* event) override;
diff --git a/ui/file_manager/base/js/filtered_volume_manager.js b/ui/file_manager/base/js/filtered_volume_manager.js index 92a0b0a..3e08cbb 100644 --- a/ui/file_manager/base/js/filtered_volume_manager.js +++ b/ui/file_manager/base/js/filtered_volume_manager.js
@@ -83,6 +83,8 @@ this.volumeInfoList = new FilteredVolumeInfoList(this.list_); this.volumeManager_ = null; + + /** @private {?Array<function()>} */ this.pendingTasks_ = []; this.onEventBound_ = this.onEvent_.bind(this); this.onVolumeInfoListUpdatedBound_ = @@ -335,7 +337,7 @@ /** * Obtains a volume information of the current profile. * @param {VolumeManagerCommon.VolumeType} volumeType Volume type. - * @return {VolumeInfo} Found volume info. + * @return {?VolumeInfo} Found volume info. */ getCurrentProfileVolumeInfo(volumeType) { return this.filterDisallowedVolume_( @@ -365,7 +367,7 @@ * Obtains location information from an entry. * * @param {(!Entry|!FilesAppEntry)} entry File or directory entry. - * @return {EntryLocation} Location information. + * @return {?EntryLocation} Location information. */ getLocationInfo(entry) { const locationInfo = @@ -399,15 +401,15 @@ * @return {!Promise<!VolumeInfo>} The VolumeInfo. Will not resolve * if the volume is never mounted. */ - whenVolumeInfoReady(volumeId) { - return new Promise(resolve => { - this.volumeManager_.whenVolumeInfoReady(volumeId).then((volumeInfo) => { - volumeInfo = this.filterDisallowedVolume_(volumeInfo); - if (volumeInfo) { - resolve(volumeInfo); - } - }); - }); + async whenVolumeInfoReady(volumeId) { + const volumeInfo = this.filterDisallowedVolume_( + await this.volumeManager_.whenVolumeInfoReady(volumeId)); + + if (!volumeInfo) { + throw new Error(`Volume not allowed: ${volumeId}`); + } + + return volumeInfo; } /** @@ -455,8 +457,7 @@ if (this.pendingTasks_) { return new Promise((fulfill, reject) => { this.pendingTasks_.push(() => { - return this.volumeManager_.configure(volumeInfo) - .then(fulfill, reject); + this.volumeManager_.configure(volumeInfo).then(fulfill, reject); }); }); } @@ -467,8 +468,8 @@ /** * Filters volume info by isAllowedVolume_(). * - * @param {VolumeInfo} volumeInfo Volume info. - * @return {VolumeInfo} Null if the volume is disallowed. Otherwise just + * @param {?VolumeInfo} volumeInfo Volume info. + * @return {?VolumeInfo} Null if the volume is disallowed. Otherwise just * returns the volume. * @private */
diff --git a/ui/file_manager/file_manager/background/js/volume_manager_factory.js b/ui/file_manager/file_manager/background/js/volume_manager_factory.js index de56fbe..57aa45e5 100644 --- a/ui/file_manager/file_manager/background/js/volume_manager_factory.js +++ b/ui/file_manager/file_manager/background/js/volume_manager_factory.js
@@ -11,9 +11,9 @@ let instance = null; /** - * @type {?Promise<!VolumeManager>} + * @type {?Promise<void>} */ - let instancePromise = null; + let instanceInitialized = null; /** * Returns the VolumeManager instance asynchronously. If it has not been @@ -22,13 +22,14 @@ * @return {!Promise<!VolumeManager>} Promise to be fulfilled with the volume * manager. */ - function getInstance() { - if (!instancePromise) { + async function getInstance() { + if (!instance) { instance = new VolumeManagerImpl(); - instancePromise = - new Promise(fulfill => instance.initialize(() => fulfill(instance))); + instanceInitialized = + new Promise(fulfill => instance.initialize(fulfill)); } - return instancePromise; + await instanceInitialized; + return instance; } /** @@ -45,7 +46,7 @@ * Revokes the singleton instance for testing. */ function revokeInstanceForTesting() { - instancePromise = null; + instanceInitialized = null; instance = null; }
diff --git a/ui/file_manager/file_manager/background/js/volume_manager_impl.js b/ui/file_manager/file_manager/background/js/volume_manager_impl.js index 26ff613..f817e62 100644 --- a/ui/file_manager/file_manager/background/js/volume_manager_impl.js +++ b/ui/file_manager/file_manager/background/js/volume_manager_impl.js
@@ -125,32 +125,30 @@ initialize(callback) { chrome.fileManagerPrivate.onMountCompleted.addListener( this.onMountCompleted_.bind(this)); - console.warn('Requesting volume list.'); + console.warn('Getting volume list'); chrome.fileManagerPrivate.getVolumeMetadataList(volumeMetadataList => { - console.warn( - 'Volume list fetched with: ' + volumeMetadataList.length + ' items.'); + console.warn(`There are ${volumeMetadataList.length} volumes`); // We must subscribe to the mount completed event in the callback of // getVolumeMetadataList. crbug.com/330061. // But volumes reported by onMountCompleted events must be added after the // volumes in the volumeMetadataList are mounted. crbug.com/135477. - this.mountQueue_.run(inCallback => { - // Create VolumeInfo for each volume. - Promise - .all(volumeMetadataList.map(volumeMetadata => { - console.warn('Initializing volume: ' + volumeMetadata.volumeId); - return this.addVolumeMetadata_(volumeMetadata) - .then(volumeInfo => { - console.warn('Initialized volume: ' + volumeInfo.volumeId); - }); - })) - .then(() => { - console.warn('Initialized all volumes.'); - // Call the callback of the initialize function. - callback(); - // Call the callback of AsyncQueue. Maybe it invokes callbacks - // registered by mountCompleted events. - inCallback(); - }); + this.mountQueue_.run(async (inCallback) => { + try { + // Create VolumeInfo for each volume. + await Promise.all(volumeMetadataList.map(async (volumeMetadata) => { + console.warn(`Initializing volume ${volumeMetadata.volumeId}`); + const volumeInfo = await this.addVolumeMetadata_(volumeMetadata); + console.warn(`Initialized volume ${volumeInfo.volumeId}`); + })); + + console.warn('Initialized all volumes'); + } finally { + // Call the callback of the initialize function. + callback(); + // Call the callback of AsyncQueue. Maybe it invokes callbacks + // registered by mountCompleted events. + inCallback(); + } }); }); }
diff --git a/ui/file_manager/file_manager/foreground/js/BUILD.gn b/ui/file_manager/file_manager/foreground/js/BUILD.gn index 91fabdd..2614000 100644 --- a/ui/file_manager/file_manager/foreground/js/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/BUILD.gn
@@ -136,7 +136,6 @@ ":folder_shortcuts_data_model", "../../common/js:util", "metadata:metadata_model", - "ui:error_dialog", "ui:files_alert_dialog", "ui:list_container", "//ui/file_manager/file_manager/foreground/js/ui:action_model_ui",
diff --git a/ui/file_manager/file_manager/foreground/js/actions_model_unittest.js b/ui/file_manager/file_manager/foreground/js/actions_model_unittest.js index 870ca868a..c383577e 100644 --- a/ui/file_manager/file_manager/foreground/js/actions_model_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/actions_model_unittest.js
@@ -71,10 +71,6 @@ this.alertDialog = /** @type {!FilesAlertDialog} */ ({ showHtml: function() {}, }); - - this.errorDialog = /** @type {!ErrorDialog} */ ({ - showHtml: function() {}, - }); } }
diff --git a/ui/file_manager/file_manager/foreground/js/main_scripts.js b/ui/file_manager/file_manager/foreground/js/main_scripts.js index 157303229..f2610ecd 100644 --- a/ui/file_manager/file_manager/foreground/js/main_scripts.js +++ b/ui/file_manager/file_manager/foreground/js/main_scripts.js
@@ -158,7 +158,6 @@ // <include src="ui/directory_tree.js"> // <include src="ui/drag_selector.js"> // <include src="ui/empty_folder.js"> -// <include src="ui/error_dialog.js"> // <include src="ui/file_grid.js"> // <include src="ui/file_manager_ui.js"> // <include src="ui/file_metadata_formatter.js">
diff --git a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn index 6b21c8b..81296ea 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
@@ -29,7 +29,6 @@ ":directory_tree", ":drag_selector", ":empty_folder", - ":error_dialog", ":file_grid", ":file_list_selection_model", ":file_manager_dialog_base", @@ -79,7 +78,6 @@ js_library("action_model_ui") { deps = [ - ":error_dialog", ":files_alert_dialog", ":list_container", ] @@ -189,12 +187,6 @@ ] } -js_library("error_dialog") { - deps = [ - "//ui/webui/resources/js/cr/ui:dialogs", - ] -} - js_library("file_grid") { deps = [ ":drag_selector", @@ -242,7 +234,6 @@ ":dialog_footer", ":directory_tree", ":empty_folder", - ":error_dialog", ":file_grid", ":file_table", ":files_alert_dialog",
diff --git a/ui/file_manager/file_manager/foreground/js/ui/action_model_ui.js b/ui/file_manager/file_manager/foreground/js/ui/action_model_ui.js index a3a7ec3..e6c3c8fa 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/action_model_ui.js +++ b/ui/file_manager/file_manager/foreground/js/ui/action_model_ui.js
@@ -7,8 +7,7 @@ constructor() { /** @type {!FilesAlertDialog} */ this.alertDialog; - /** @type {!ErrorDialog} */ - this.errorDialog; + /** @type {!ListContainer} */ this.listContainer; }
diff --git a/ui/file_manager/file_manager/foreground/js/ui/default_task_dialog.js b/ui/file_manager/file_manager/foreground/js/ui/default_task_dialog.js index 9e42d22..244bbf17 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/default_task_dialog.js +++ b/ui/file_manager/file_manager/foreground/js/ui/default_task_dialog.js
@@ -10,158 +10,158 @@ cr.define('cr.filebrowser', () => { /** * Creates dialog in DOM tree. - * - * @param {HTMLElement} parentNode Node to be parent for this dialog. - * @constructor - * @extends {FileManagerDialogBase} */ - function DefaultTaskDialog(parentNode) { - FileManagerDialogBase.call(this, parentNode); + class DefaultTaskDialog extends FileManagerDialogBase { + /** + * @param {HTMLElement} parentNode Node to be parent for this dialog. + */ + constructor(parentNode) { + super(parentNode); - this.frame_.id = 'default-task-dialog'; + this.frame_.id = 'default-task-dialog'; - this.list_ = new cr.ui.List(); - this.list_.id = 'default-tasks-list'; - this.frame_.insertBefore(this.list_, this.text_.nextSibling); + this.list_ = new cr.ui.List(); + this.list_.id = 'default-tasks-list'; + this.frame_.insertBefore(this.list_, this.text_.nextSibling); - this.selectionModel_ = this.list_.selectionModel = - new cr.ui.ListSingleSelectionModel(); - this.dataModel_ = this.list_.dataModel = new cr.ui.ArrayDataModel([]); + this.selectionModel_ = this.list_.selectionModel = + new cr.ui.ListSingleSelectionModel(); + this.dataModel_ = this.list_.dataModel = new cr.ui.ArrayDataModel([]); - // List has max-height defined at css, so that list grows automatically, - // but doesn't exceed predefined size. - this.list_.autoExpands = true; - this.list_.activateItemAtIndex = this.activateItemAtIndex_.bind(this); - // Use 'click' instead of 'change' for keyboard users. - this.list_.addEventListener('click', this.onSelected_.bind(this)); - this.list_.addEventListener('change', this.onListChange_.bind(this)); + // List has max-height defined at css, so that list grows automatically, + // but doesn't exceed predefined size. + this.list_.autoExpands = true; + this.list_.activateItemAtIndex = this.activateItemAtIndex_.bind(this); + // Use 'click' instead of 'change' for keyboard users. + this.list_.addEventListener('click', this.onSelected_.bind(this)); + this.list_.addEventListener('change', this.onListChange_.bind(this)); - this.initialFocusElement_ = this.list_; + this.initialFocusElement_ = this.list_; - const self = this; + /** @private {?function(*)} */ + this.onSelectedItemCallback_ = null; - // Binding stuff doesn't work with constructors, so we have to create - // closure here. - this.list_.itemConstructor = function(item) { - return self.renderItem(item); - }; - } + const self = this; - DefaultTaskDialog.prototype = {__proto__: FileManagerDialogBase.prototype}; - - /** - * Renders item for list. - * @param {Object} item Item to render. - */ - DefaultTaskDialog.prototype.renderItem = function(item) { - const result = this.document_.createElement('li'); - - const div = this.document_.createElement('div'); - div.textContent = item.label; - - if (item.iconType) { - div.setAttribute('file-type-icon', item.iconType); - } else if (item.iconUrl) { - div.style.backgroundImage = 'url(' + item.iconUrl + ')'; + // Binding stuff doesn't work with constructors, so we have to create + // closure here. + this.list_.itemConstructor = function(item) { + return self.renderItem(item); + }; } - if (item.class) { - div.classList.add(item.class); + /** + * Renders item for list. + * @param {Object} item Item to render. + */ + renderItem(item) { + const result = this.document_.createElement('li'); + + const div = this.document_.createElement('div'); + div.textContent = item.label; + + if (item.iconType) { + div.setAttribute('file-type-icon', item.iconType); + } else if (item.iconUrl) { + div.style.backgroundImage = 'url(' + item.iconUrl + ')'; + } + + if (item.class) { + div.classList.add(item.class); + } + + result.appendChild(div); + // A11y - make it focusable and readable. + result.setAttribute('tabindex', '-1'); + + cr.defineProperty(result, 'lead', cr.PropertyKind.BOOL_ATTR); + cr.defineProperty(result, 'selected', cr.PropertyKind.BOOL_ATTR); + + return result; } - result.appendChild(div); - // A11y - make it focusable and readable. - result.setAttribute('tabindex', '-1'); + /** + * Shows dialog. + * + * @param {string} title Title in dialog caption. + * @param {string} message Message in dialog caption. + * @param {Array<Object>} items Items to render in the list. + * @param {number} defaultIndex Item to select by default. + * @param {function(*)} onSelectedItem Callback which is called when an item + * is selected. + */ + showDefaultTaskDialog(title, message, items, defaultIndex, onSelectedItem) { + this.onSelectedItemCallback_ = onSelectedItem; - cr.defineProperty(result, 'lead', cr.PropertyKind.BOOL_ATTR); - cr.defineProperty(result, 'selected', cr.PropertyKind.BOOL_ATTR); + const show = super.showTitleAndTextDialog(title, message); - return result; - }; + if (!show) { + console.error('DefaultTaskDialog can\'t be shown.'); + return; + } - /** - * Shows dialog. - * - * @param {string} title Title in dialog caption. - * @param {string} message Message in dialog caption. - * @param {Array<Object>} items Items to render in the list. - * @param {number} defaultIndex Item to select by default. - * @param {function(Object)} onSelectedItem Callback which is called when an - * item is selected. - */ - DefaultTaskDialog.prototype.showDefaultTaskDialog = function( - title, message, items, defaultIndex, onSelectedItem) { - this.onSelectedItemCallback_ = onSelectedItem; + if (!message) { + this.text_.setAttribute('hidden', 'hidden'); + } else { + this.text_.removeAttribute('hidden'); + } - const show = FileManagerDialogBase.prototype.showTitleAndTextDialog.call( - this, title, message); - - if (!show) { - console.error('DefaultTaskDialog can\'t be shown.'); - return; + this.list_.startBatchUpdates(); + this.dataModel_.splice(0, this.dataModel_.length); + for (let i = 0; i < items.length; i++) { + this.dataModel_.push(items[i]); + } + this.selectionModel_.selectedIndex = defaultIndex; + this.list_.endBatchUpdates(); } - if (!message) { - this.text_.setAttribute('hidden', 'hidden'); - } else { - this.text_.removeAttribute('hidden'); - } - - this.list_.startBatchUpdates(); - this.dataModel_.splice(0, this.dataModel_.length); - for (let i = 0; i < items.length; i++) { - this.dataModel_.push(items[i]); - } - this.selectionModel_.selectedIndex = defaultIndex; - this.list_.endBatchUpdates(); - }; - - /** - * List activation handler. Closes dialog and calls 'ok' callback. - * @param {number} index Activated index. - */ - DefaultTaskDialog.prototype.activateItemAtIndex_ = function(index) { - this.hide(); - this.onSelectedItemCallback_(this.dataModel_.item(index)); - }; - - /** - * Closes dialog and invokes callback with currently-selected item. - */ - DefaultTaskDialog.prototype.onSelected_ = function() { - if (this.selectionModel_.selectedIndex !== -1) { - this.activateItemAtIndex_(this.selectionModel_.selectedIndex); - } - }; - - /** - * Called when cr.ui.List triggers a change event, which means user - * focused a new item on the list. Used here to isue .focus() on - * currently active item so ChromeVox can read it out. - * @param {!Event} event triggered by cr.ui.List. - */ - DefaultTaskDialog.prototype.onListChange_ = event => { - const list = /** @type {cr.ui.List} */ (event.target); - const activeItem = - list.getListItemByIndex(list.selectionModel_.selectedIndex); - if (activeItem) { - activeItem.focus(); - } - }; - - /** - * @override - */ - DefaultTaskDialog.prototype.onContainerKeyDown_ = function(event) { - // Handle Escape. - if (event.keyCode == 27) { + /** + * List activation handler. Closes dialog and calls 'ok' callback. + * @param {number} index Activated index. + */ + activateItemAtIndex_(index) { this.hide(); - event.preventDefault(); - } else if (event.keyCode == 32 || event.keyCode == 13) { - this.onSelected_(); - event.preventDefault(); + this.onSelectedItemCallback_(this.dataModel_.item(index)); } - }; + + /** + * Closes dialog and invokes callback with currently-selected item. + */ + onSelected_() { + if (this.selectionModel_.selectedIndex !== -1) { + this.activateItemAtIndex_(this.selectionModel_.selectedIndex); + } + } + + /** + * Called when cr.ui.List triggers a change event, which means user + * focused a new item on the list. Used here to issue .focus() on + * currently active item so ChromeVox can read it out. + * @param {!Event} event triggered by cr.ui.List. + */ + onListChange_(event) { + const list = /** @type {cr.ui.List} */ (event.target); + const activeItem = + list.getListItemByIndex(list.selectionModel_.selectedIndex); + if (activeItem) { + activeItem.focus(); + } + } + + /** + * @override + */ + onContainerKeyDown_(event) { + // Handle Escape. + if (event.keyCode == 27) { + this.hide(); + event.preventDefault(); + } else if (event.keyCode == 32 || event.keyCode == 13) { + this.onSelected_(); + event.preventDefault(); + } + } + } return {DefaultTaskDialog: DefaultTaskDialog}; });
diff --git a/ui/file_manager/file_manager/foreground/js/ui/error_dialog.js b/ui/file_manager/file_manager/foreground/js/ui/error_dialog.js deleted file mode 100644 index e53685d4..0000000 --- a/ui/file_manager/file_manager/foreground/js/ui/error_dialog.js +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @param {HTMLElement} parentNode Node to be parent for this dialog. - * @constructor - * @extends {cr.ui.dialogs.BaseDialog} - */ -function ErrorDialog(parentNode) { - cr.ui.dialogs.BaseDialog.call(this, parentNode); -} - -ErrorDialog.prototype = { - __proto__: cr.ui.dialogs.BaseDialog.prototype -}; - -/** - * One-time initialization of DOM. - * @protected - */ -ErrorDialog.prototype.initDom_ = function() { - cr.ui.dialogs.BaseDialog.prototype.initDom_.call(this); - this.frame_.classList.add('error-dialog-frame'); - const img = this.document_.createElement('div'); - img.className = 'error-dialog-img'; - this.frame_.insertBefore(img, this.text_); -};
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_manager_dialog_base.js b/ui/file_manager/file_manager/foreground/js/ui/file_manager_dialog_base.js index 8a97087..b3953fd 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_manager_dialog_base.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_manager_dialog_base.js
@@ -4,18 +4,94 @@ /** * This class is an extended class, to manage the status of the dialogs. - * - * @param {HTMLElement} parentNode Parent node of the dialog. - * @extends {cr.ui.dialogs.BaseDialog} - * @constructor */ -const FileManagerDialogBase = function(parentNode) { - cr.ui.dialogs.BaseDialog.call(this, parentNode); -}; +class FileManagerDialogBase extends cr.ui.dialogs.BaseDialog { + /** + * @param {HTMLElement} parentNode Parent node of the dialog. + */ + constructor(parentNode) { + super(parentNode); + } -FileManagerDialogBase.prototype = { - __proto__: cr.ui.dialogs.BaseDialog.prototype -}; + /** + * @param {string} title Title. + * @param {string} message Message. + * @param {?function()} onOk Called when the OK button is pressed. + * @param {?function()} onCancel Called when the cancel button is pressed. + * @return {boolean} True if the dialog can show successfully. False if the + * dialog failed to show due to an existing dialog. + */ + showOkCancelDialog(title, message, onOk, onCancel) { + return this.showImpl_(title, message, onOk, onCancel); + } + + /** + * @param {string} title Title. + * @param {string} message Message. + * @param {?function()} onOk Called when the OK button is pressed. + * @param {?function()} onCancel Called when the cancel button is pressed. + * @return {boolean} True if the dialog can show successfully. False if the + * dialog failed to show due to an existing dialog. + * @private + */ + showImpl_(title, message, onOk, onCancel) { + if (FileManagerDialogBase.shown) { + return false; + } + + FileManagerDialogBase.shown = true; + + // If a dialog is shown, activate the window. + const appWindow = chrome.app.window.current(); + if (appWindow) { + appWindow.focus(); + } + + super.showWithTitle(title, message, onOk, onCancel, null); + + return true; + } + + /** + * @return {boolean} True if the dialog can show successfully. False if the + * dialog failed to show due to an existing dialog. + */ + showBlankDialog() { + return this.showImpl_('', '', null, null); + } + + /** + * @param {string} title Title. + * @return {boolean} True if the dialog can show successfully. False if the + * dialog failed to show due to an existing dialog. + */ + showTitleOnlyDialog(title) { + return this.showImpl_(title, '', null, null); + } + + /** + * @param {string} title Title. + * @param {string} text Text to be shown in the dialog. + * @return {boolean} True if the dialog can show successfully. False if the + * dialog failed to show due to an existing dialog. + */ + showTitleAndTextDialog(title, text) { + this.buttons.style.display = 'none'; + return this.showImpl_(title, text, null, null); + } + + /** + * @param {Function=} opt_onHide Called when the dialog is hidden. + */ + hide(opt_onHide) { + super.hide(() => { + if (opt_onHide) { + opt_onHide(); + } + FileManagerDialogBase.shown = false; + }); + } +} /** * The flag if any dialog is shown. True if a dialog is visible, false @@ -23,85 +99,3 @@ * @type {boolean} */ FileManagerDialogBase.shown = false; - -/** - * @param {string} title Title. - * @param {string} message Message. - * @param {?function()} onOk Called when the OK button is pressed. - * @param {?function()} onCancel Called when the cancel button is pressed. - * @return {boolean} True if the dialog can show successfully. False if the - * dialog failed to show due to an existing dialog. - */ -FileManagerDialogBase.prototype.showOkCancelDialog = function( - title, message, onOk, onCancel) { - return this.showImpl_(title, message, onOk, onCancel); -}; - -/** - * @param {string} title Title. - * @param {string} message Message. - * @param {?function()} onOk Called when the OK button is pressed. - * @param {?function()} onCancel Called when the cancel button is pressed. - * @return {boolean} True if the dialog can show successfully. False if the - * dialog failed to show due to an existing dialog. - * @private - */ -FileManagerDialogBase.prototype.showImpl_ = function( - title, message, onOk, onCancel) { - if (FileManagerDialogBase.shown) { - return false; - } - - FileManagerDialogBase.shown = true; - - // If a dialog is shown, activate the window. - const appWindow = chrome.app.window.current(); - if (appWindow) { - appWindow.focus(); - } - - cr.ui.dialogs.BaseDialog.prototype.showWithTitle.call( - this, title, message, onOk, onCancel, null); - - return true; -}; - -/** - * @return {boolean} True if the dialog can show successfully. False if the - * dialog failed to show due to an existing dialog. - */ -FileManagerDialogBase.prototype.showBlankDialog = function() { - return this.showImpl_('', '', null, null); -}; - -/** - * @param {string} title Title. - * @return {boolean} True if the dialog can show successfully. False if the - * dialog failed to show due to an existing dialog. - */ -FileManagerDialogBase.prototype.showTitleOnlyDialog = function(title) { - return this.showImpl_(title, '', null, null); -}; - -/** - * @param {string} title Title. - * @param {string} text Text to be shown in the dialog. - * @return {boolean} True if the dialog can show successfully. False if the - * dialog failed to show due to an existing dialog. - */ -FileManagerDialogBase.prototype.showTitleAndTextDialog = function(title, text) { - this.buttons.style.display = 'none'; - return this.showImpl_(title, text, null, null); -}; - -/** - * @param {Function=} opt_onHide Called when the dialog is hidden. - */ -FileManagerDialogBase.prototype.hide = function(opt_onHide) { - cr.ui.dialogs.BaseDialog.prototype.hide.call(this, () => { - if (opt_onHide) { - opt_onHide(); - } - FileManagerDialogBase.shown = false; - }); -};
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js index fc72478..218a9b8 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js
@@ -42,13 +42,6 @@ this.separators_ = [].slice.call(document.querySelectorAll('cr-menu > hr')); /** - * Error dialog. - * @type {!ErrorDialog} - * @const - */ - this.errorDialog = new ErrorDialog(this.element); - - /** * Alert dialog. * @type {!FilesAlertDialog} * @const
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table.js b/ui/file_manager/file_manager/foreground/js/ui/file_table.js index dd65a40..0e627c1 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_table.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_table.js
@@ -4,13 +4,234 @@ /** * Custom column model for advanced auto-resizing. - * - * @param {!Array<cr.ui.table.TableColumn>} tableColumns Table columns. - * @extends {cr.ui.table.TableColumnModel} - * @constructor */ -function FileTableColumnModel(tableColumns) { - cr.ui.table.TableColumnModel.call(this, tableColumns); +class FileTableColumnModel extends cr.ui.table.TableColumnModel { + /** + * @param {!Array<cr.ui.table.TableColumn>} tableColumns Table columns. + */ + constructor(tableColumns) { + super(tableColumns); + + /** @private {?FileTableColumnModel.ColumnSnapshot} */ + this.snapshot_ = null; + } + + /** + * Sets column width so that the column dividers move to the specified + * position. This function also check the width of each column and keep the + * width larger than MIN_WIDTH_. + * + * @private + * @param {Array<number>} newPos Positions of each column dividers. + */ + applyColumnPositions_(newPos) { + // Check the minimum width and adjust the positions. + for (let i = 0; i < newPos.length - 2; i++) { + if (!this.columns_[i].visible) { + newPos[i + 1] = newPos[i]; + } else if (newPos[i + 1] - newPos[i] < FileTableColumnModel.MIN_WIDTH_) { + newPos[i + 1] = newPos[i] + FileTableColumnModel.MIN_WIDTH_; + } + } + for (let i = newPos.length - 1; i >= 2; i--) { + if (!this.columns_[i - 1].visible) { + newPos[i - 1] = newPos[i]; + } else if (newPos[i] - newPos[i - 1] < FileTableColumnModel.MIN_WIDTH_) { + newPos[i - 1] = newPos[i] - FileTableColumnModel.MIN_WIDTH_; + } + } + // Set the new width of columns + for (let i = 0; i < this.columns_.length; i++) { + if (!this.columns_[i].visible) { + this.columns_[i].width = 0; + } else { + // Make sure each cell has the minimum width. This is necessary when the + // window size is too small to contain all the columns. + this.columns_[i].width = Math.max( + FileTableColumnModel.MIN_WIDTH_, newPos[i + 1] - newPos[i]); + } + } + } + + /** + * Normalizes widths to make their sum 100% if possible. Uses the proportional + * approach with some additional constraints. + * + * @param {number} contentWidth Target width. + * @override + */ + normalizeWidths(contentWidth) { + let totalWidth = 0; + // Some columns have fixed width. + for (let i = 0; i < this.columns_.length; i++) { + totalWidth += this.columns_[i].width; + } + const positions = [0]; + let sum = 0; + for (let i = 0; i < this.columns_.length; i++) { + const column = this.columns_[i]; + sum += column.width; + // Faster alternative to Math.floor for non-negative numbers. + positions[i + 1] = ~~(contentWidth * sum / totalWidth); + } + this.applyColumnPositions_(positions); + } + + /** + * Handles to the start of column resizing by splitters. + */ + handleSplitterDragStart() { + this.initializeColumnPos(); + } + + /** + * Handles to the end of column resizing by splitters. + */ + handleSplitterDragEnd() { + this.destroyColumnPos(); + } + + /** + * Initialize a column snapshot which is used in setWidthAndKeepTotal(). + */ + initializeColumnPos() { + this.snapshot_ = new FileTableColumnModel.ColumnSnapshot(this.columns_); + } + + /** + * Destroy the column snapshot which is used in setWidthAndKeepTotal(). + */ + destroyColumnPos() { + this.snapshot_ = null; + } + + /** + * Sets the width of column while keeping the total width of table. + * Before and after calling this method, you must initialize and destroy + * columnPos with initializeColumnPos() and destroyColumnPos(). + * @param {number} columnIndex Index of column that is resized. + * @param {number} columnWidth New width of the column. + */ + setWidthAndKeepTotal(columnIndex, columnWidth) { + columnWidth = Math.max(columnWidth, FileTableColumnModel.MIN_WIDTH_); + this.snapshot_.setWidth(columnIndex, columnWidth); + this.applyColumnPositions_(this.snapshot_.newPos); + + // Notify about resizing + cr.dispatchSimpleEvent(this, 'resize'); + } + + /** + * Obtains a column by the specified horizontal position. + * @param {number} x Horizontal position. + * @return {Object} The object that contains column index, column width, and + * hitPosition where the horizontal position is hit in the column. + */ + getHitColumn(x) { + for (var i = 0; x >= this.columns_[i].width; i++) { + x -= this.columns_[i].width; + } + if (i >= this.columns_.length) { + return null; + } + return {index: i, hitPosition: x, width: this.columns_[i].width}; + } + + /** @override */ + setVisible(index, visible) { + if (index < 0 || index > this.columns_.length - 1) { + return; + } + + const column = this.columns_[index]; + if (column.visible === visible) { + return; + } + + // Re-layout the table. This overrides the default column layout code in + // the parent class. + const snapshot = new FileTableColumnModel.ColumnSnapshot(this.columns_); + + column.visible = visible; + + // Keep the current column width, but adjust the other columns to + // accommodate the new column. + snapshot.setWidth(index, column.width); + this.applyColumnPositions_(snapshot.newPos); + } + + /** + * Export a set of column widths for use by #restoreColumnWidths. Use these + * two methods instead of manually saving and setting column widths, because + * doing the latter will not correctly save/restore column widths for hidden + * columns. + * @see #restoreColumnWidths + * @return {!Object} config + */ + exportColumnConfig() { + // Make a snapshot, and use that to compute a column layout where all the + // columns are visible. + const snapshot = new FileTableColumnModel.ColumnSnapshot(this.columns_); + for (let i = 0; i < this.columns_.length; i++) { + if (!this.columns_[i].visible) { + snapshot.setWidth(i, this.columns_[i].absoluteWidth); + } + } + // Export the column widths. + const config = {}; + for (let i = 0; i < this.columns_.length; i++) { + config[this.columns_[i].id] = { + width: snapshot.newPos[i + 1] - snapshot.newPos[i] + }; + } + return config; + } + + /** + * Restores a set of column widths previously created by calling + * #exportColumnConfig. + * @see #exportColumnConfig + * @param {!Object} config + */ + restoreColumnConfig(config) { + // Convert old-style raw column widths into new-style config objects. + if (Array.isArray(config)) { + const tmpConfig = {}; + tmpConfig[this.columns_[0].id] = config[0]; + tmpConfig[this.columns_[1].id] = config[1]; + tmpConfig[this.columns_[3].id] = config[2]; + tmpConfig[this.columns_[4].id] = config[3]; + config = tmpConfig; + } + + // Columns must all be made visible before restoring their widths. Save the + // current visibility so it can be restored after. + const visibility = []; + for (let i = 0; i < this.columns_.length; i++) { + visibility[i] = this.columns_[i].visible; + this.columns_[i].visible = true; + } + + // Do not use external setters (e.g. #setVisible, #setWidth) here because + // they trigger layout thrash, and also try to dynamically resize columns, + // which interferes with restoring the old column layout. + for (const columnId in config) { + const column = this.columns_[this.indexOf(columnId)]; + if (column) { + // Set column width. Ignore invalid widths. + const width = ~~config[columnId].width; + if (width > 0) { + column.width = width; + } + } + } + + // Restore column visibility. Use setVisible here, to trigger table + // relayout. + for (let i = 0; i < this.columns_.length; i++) { + this.setVisible(i, visibility[i]); + } + } } /** @@ -40,12 +261,6 @@ } /** - * Inherits from cr.ui.TableColumnModel. - */ -FileTableColumnModel.prototype.__proto__ = - cr.ui.table.TableColumnModel.prototype; - -/** * Minimum width of column. Note that is not marked private as it is used in the * unit tests. * @const {number} @@ -53,273 +268,59 @@ FileTableColumnModel.MIN_WIDTH_ = 10; /** - * Sets column width so that the column dividers move to the specified position. - * This function also check the width of each column and keep the width larger - * than MIN_WIDTH_. - * - * @private - * @param {Array<number>} newPos Positions of each column dividers. - */ -FileTableColumnModel.prototype.applyColumnPositions_ = function(newPos) { - // Check the minimum width and adjust the positions. - for (let i = 0; i < newPos.length - 2; i++) { - if (!this.columns_[i].visible) { - newPos[i + 1] = newPos[i]; - } else if (newPos[i + 1] - newPos[i] < FileTableColumnModel.MIN_WIDTH_) { - newPos[i + 1] = newPos[i] + FileTableColumnModel.MIN_WIDTH_; - } - } - for (let i = newPos.length - 1; i >= 2; i--) { - if (!this.columns_[i - 1].visible) { - newPos[i - 1] = newPos[i]; - } else if (newPos[i] - newPos[i - 1] < FileTableColumnModel.MIN_WIDTH_) { - newPos[i - 1] = newPos[i] - FileTableColumnModel.MIN_WIDTH_; - } - } - // Set the new width of columns - for (let i = 0; i < this.columns_.length; i++) { - if (!this.columns_[i].visible) { - this.columns_[i].width = 0; - } else { - // Make sure each cell has the minumum width. This is necessary when the - // window size is too small to contain all the columns. - this.columns_[i].width = - Math.max(FileTableColumnModel.MIN_WIDTH_, newPos[i + 1] - newPos[i]); - } - } -}; - -/** - * Normalizes widths to make their sum 100% if possible. Uses the proportional - * approach with some additional constraints. - * - * @param {number} contentWidth Target width. - * @override - */ -FileTableColumnModel.prototype.normalizeWidths = function(contentWidth) { - let totalWidth = 0; - // Some columns have fixed width. - for (let i = 0; i < this.columns_.length; i++) { - totalWidth += this.columns_[i].width; - } - const positions = [0]; - let sum = 0; - for (let i = 0; i < this.columns_.length; i++) { - const column = this.columns_[i]; - sum += column.width; - // Faster alternative to Math.floor for non-negative numbers. - positions[i + 1] = ~~(contentWidth * sum / totalWidth); - } - this.applyColumnPositions_(positions); -}; - -/** - * Handles to the start of column resizing by splitters. - */ -FileTableColumnModel.prototype.handleSplitterDragStart = function() { - this.initializeColumnPos(); -}; - -/** - * Handles to the end of column resizing by splitters. - */ -FileTableColumnModel.prototype.handleSplitterDragEnd = function() { - this.destroyColumnPos(); -}; - -/** - * Initialize a column snapshot which is used in setWidthAndKeepTotal(). - */ -FileTableColumnModel.prototype.initializeColumnPos = function() { - this.snapshot_ = new FileTableColumnModel.ColumnSnapshot(this.columns_); -}; - -/** - * Destroy the column snapshot which is used in setWidthAndKeepTotal(). - */ -FileTableColumnModel.prototype.destroyColumnPos = function() { - this.snapshot_ = null; -}; - -/** - * Sets the width of column while keeping the total width of table. - * Before and after calling this method, you must initialize and destroy - * columnPos with initializeColumnPos() and destroyColumnPos(). - * @param {number} columnIndex Index of column that is resized. - * @param {number} columnWidth New width of the column. - */ -FileTableColumnModel.prototype.setWidthAndKeepTotal = function( - columnIndex, columnWidth) { - columnWidth = Math.max(columnWidth, FileTableColumnModel.MIN_WIDTH_); - this.snapshot_.setWidth(columnIndex, columnWidth); - this.applyColumnPositions_(this.snapshot_.newPos); - - // Notify about resizing - cr.dispatchSimpleEvent(this, 'resize'); -}; - -/** - * Obtains a column by the specified horizontal position. - * @param {number} x Horizontal position. - * @return {Object} The object that contains column index, column width, and - * hitPosition where the horizontal position is hit in the column. - */ -FileTableColumnModel.prototype.getHitColumn = function(x) { - for (var i = 0; x >= this.columns_[i].width; i++) { - x -= this.columns_[i].width; - } - if (i >= this.columns_.length) { - return null; - } - return {index: i, hitPosition: x, width: this.columns_[i].width}; -}; - -/** @override */ -FileTableColumnModel.prototype.setVisible = function(index, visible) { - if (index < 0 || index > this.columns_.length - 1) { - return; - } - - const column = this.columns_[index]; - if (column.visible === visible) { - return; - } - - // Re-layout the table. This overrides the default column layout code in the - // parent class. - const snapshot = new FileTableColumnModel.ColumnSnapshot(this.columns_); - - column.visible = visible; - - // Keep the current column width, but adjust the other columns to accomodate - // the new column. - snapshot.setWidth(index, column.width); - this.applyColumnPositions_(snapshot.newPos); -}; - -/** - * Export a set of column widths for use by #restoreColumnWidths. Use these two - * methods instead of manually saving and setting column widths, because doing - * the latter will not correctly save/restore column widths for hidden columns. - * @see #restoreColumnWidths - * @return {!Object} config - */ -FileTableColumnModel.prototype.exportColumnConfig = function() { - // Make a snapshot, and use that to compute a column layout where all the - // columns are visible. - const snapshot = new FileTableColumnModel.ColumnSnapshot(this.columns_); - for (let i = 0; i < this.columns_.length; i++) { - if (!this.columns_[i].visible) { - snapshot.setWidth(i, this.columns_[i].absoluteWidth); - } - } - // Export the column widths. - const config = {}; - for (let i = 0; i < this.columns_.length; i++) { - config[this.columns_[i].id] = { - width: snapshot.newPos[i + 1] - snapshot.newPos[i] - }; - } - return config; -}; - -/** - * Restores a set of column widths previously created by calling - * #exportColumnConfig. - * @see #exportColumnConfig - * @param {!Object} config - */ -FileTableColumnModel.prototype.restoreColumnConfig = function(config) { - // Convert old-style raw column widths into new-style config objects. - if (Array.isArray(config)) { - const tmpConfig = {}; - tmpConfig[this.columns_[0].id] = config[0]; - tmpConfig[this.columns_[1].id] = config[1]; - tmpConfig[this.columns_[3].id] = config[2]; - tmpConfig[this.columns_[4].id] = config[3]; - config = tmpConfig; - } - - // Columns must all be made visible before restoring their widths. Save the - // current visibility so it can be restored after. - const visibility = []; - for (let i = 0; i < this.columns_.length; i++) { - visibility[i] = this.columns_[i].visible; - this.columns_[i].visible = true; - } - - // Do not use external setters (e.g. #setVisible, #setWidth) here because they - // trigger layout thrash, and also try to dynamically resize columns, which - // interferes with restoring the old column layout. - for (const columnId in config) { - const column = this.columns_[this.indexOf(columnId)]; - if (column) { - // Set column width. Ignore invalid widths. - const width = ~~config[columnId].width; - if (width > 0) { - column.width = width; - } - } - } - - // Restore column visibility. Use setVisible here, to trigger table relayout. - for (let i = 0; i < this.columns_.length; i++) { - this.setVisible(i, visibility[i]); - } -}; - -/** * A helper class for performing resizing of columns. - * @param {!Array<!cr.ui.table.TableColumn>} columns - * @constructor */ -FileTableColumnModel.ColumnSnapshot = function(columns) { - /** @private {!Array<number>} */ - this.columnPos_ = [0]; - for (let i = 0; i < columns.length; i++) { - this.columnPos_[i + 1] = columns[i].width + this.columnPos_[i]; +FileTableColumnModel.ColumnSnapshot = class { + /** + * @param {!Array<!cr.ui.table.TableColumn>} columns + */ + constructor(columns) { + /** @private {!Array<number>} */ + this.columnPos_ = [0]; + for (let i = 0; i < columns.length; i++) { + this.columnPos_[i + 1] = columns[i].width + this.columnPos_[i]; + } + + /** + * Starts off as a copy of the current column positions, but gets modified. + * @private {!Array<number>} + */ + this.newPos = this.columnPos_.slice(0); } /** - * Starts off as a copy of the current column positions, but gets modified. - * @private {!Array<number>} + * Set the width of the given column. The snapshot will keep the total width + * of the table constant. + * @param {number} index + * @param {number} width */ - this.newPos = this.columnPos_.slice(0); -}; + setWidth(index, width) { + // Skip to resize 'selection' column + if (index < 0 || index >= this.columnPos_.length - 1 || !this.columnPos_) { + return; + } -/** - * Set the width of the given column. The snapshot will keep the total width of - * the table constant. - * @param {number} index - * @param {number} width - */ -FileTableColumnModel.ColumnSnapshot.prototype.setWidth = function( - index, width) { - // Skip to resize 'selection' column - if (index < 0 || index >= this.columnPos_.length - 1 || !this.columnPos_) { - return; - } + // Round up if the column is shrinking, and down if the column is expanding. + // This prevents off-by-one drift. + const currentWidth = this.columnPos_[index + 1] - this.columnPos_[index]; + const round = width < currentWidth ? Math.ceil : Math.floor; - // Round up if the column is shrinking, and down if the column is expanding. - // This prevents off-by-one drift. - const currentWidth = this.columnPos_[index + 1] - this.columnPos_[index]; - const round = width < currentWidth ? Math.ceil : Math.floor; - - // Calculate new positions of column splitters. - const newPosStart = this.columnPos_[index] + width; - const posEnd = this.columnPos_[this.columnPos_.length - 1]; - for (let i = 0; i < index + 1; i++) { - this.newPos[i] = this.columnPos_[i]; + // Calculate new positions of column splitters. + const newPosStart = this.columnPos_[index] + width; + const posEnd = this.columnPos_[this.columnPos_.length - 1]; + for (let i = 0; i < index + 1; i++) { + this.newPos[i] = this.columnPos_[i]; + } + for (let i = index + 1; i < this.columnPos_.length - 1; i++) { + const posStart = this.columnPos_[index + 1]; + this.newPos[i] = (posEnd - newPosStart) * + (this.columnPos_[i] - posStart) / (posEnd - posStart) + + newPosStart; + this.newPos[i] = round(this.newPos[i]); + } + this.newPos[index] = this.columnPos_[index]; + this.newPos[this.columnPos_.length - 1] = posEnd; } - for (let i = index + 1; i < this.columnPos_.length - 1; i++) { - const posStart = this.columnPos_[index + 1]; - this.newPos[i] = (posEnd - newPosStart) * (this.columnPos_[i] - posStart) / - (posEnd - posStart) + - newPosStart; - this.newPos[i] = round(this.newPos[i]); - } - this.newPos[index] = this.columnPos_[index]; - this.newPos[this.columnPos_.length - 1] = posEnd; }; /** @@ -360,787 +361,832 @@ /** * File list Table View. - * @constructor - * @extends {cr.ui.Table} */ -function FileTable() { - throw new Error('Designed to decorate elements'); +class FileTable extends cr.ui.Table { + constructor() { + super(); + + /** @private {number} */ + this.beginIndex_ = 0; + + /** @private {number} */ + this.endIndex_ = 0; + + /** @private {?ListThumbnailLoader} */ + this.listThumbnailLoader_ = null; + + /** @private {?AsyncUtil.RateLimiter} */ + this.relayoutRateLimiter_ = null; + + /** @private {?MetadataModel} */ + this.metadataModel_ = null; + + /** @private {?cr.ui.table.TableList} */ + this.list_ = null; + + /** @private {?FileMetadataFormatter} */ + this.formatter_ = null; + + /** @private {boolean} */ + this.useModificationByMeTime_ = false; + + /** @private {?importer.HistoryLoader} */ + this.historyLoader_ = null; + + /** @private {boolean} */ + this.importStatusVisible_ = false; + + /** @private {?VolumeManager} */ + this.volumeManager_ = null; + + /** @private {!Array} */ + this.lastSelection_ = []; + + /** @private {?function(!Event)} */ + this.onThumbnailLoadedBound_ = null; + + throw new Error('Designed to decorate elements'); + } + + /** + * Decorates the element. + * @param {!Element} self Table to decorate. + * @param {!MetadataModel} metadataModel To retrieve + * metadata. + * @param {!VolumeManager} volumeManager To retrieve volume info. + * @param {!importer.HistoryLoader} historyLoader + * @param {boolean} fullPage True if it's full page File Manager, + * False if a file open/save dialog. + */ + static decorate(self, metadataModel, volumeManager, historyLoader, fullPage) { + cr.ui.Table.decorate(self); + self.__proto__ = FileTable.prototype; + FileTableList.decorate(self.list); + self.list.setOnMergeItems(self.updateHighPriorityRange_.bind(self)); + self.metadataModel_ = metadataModel; + self.volumeManager_ = volumeManager; + self.historyLoader_ = historyLoader; + + /** @private {ListThumbnailLoader} */ + self.listThumbnailLoader_ = null; + + /** @private {number} */ + self.beginIndex_ = 0; + + /** @private {number} */ + self.endIndex_ = 0; + + /** @private {function(!Event)} */ + self.onThumbnailLoadedBound_ = self.onThumbnailLoaded_.bind(self); + + /** + * Reflects the visibility of import status in the UI. Assumption: import + * status is only enabled in import-eligible locations. See + * ImportController#onDirectoryChanged. For this reason, the code in this + * class checks if import status is visible, and if so, assumes that all + * the files are in an import-eligible location. + * TODO(kenobi): Clean this up once import status is queryable from + * metadata. + * + * @private {boolean} + */ + self.importStatusVisible_ = true; + + /** @private {boolean} */ + self.useModificationByMeTime_ = false; + + const nameColumn = new cr.ui.table.TableColumn( + 'name', str('NAME_COLUMN_LABEL'), fullPage ? 386 : 324); + nameColumn.renderFunction = self.renderName_.bind(self); + nameColumn.headerRenderFunction = renderHeader_; + + const sizeColumn = new cr.ui.table.TableColumn( + 'size', str('SIZE_COLUMN_LABEL'), 110, true); + sizeColumn.renderFunction = self.renderSize_.bind(self); + sizeColumn.defaultOrder = 'desc'; + sizeColumn.headerRenderFunction = renderHeader_; + + const statusColumn = new cr.ui.table.TableColumn( + 'status', str('STATUS_COLUMN_LABEL'), 60, true); + statusColumn.renderFunction = self.renderStatus_.bind(self); + statusColumn.visible = self.importStatusVisible_; + statusColumn.headerRenderFunction = renderHeader_; + + const typeColumn = new cr.ui.table.TableColumn( + 'type', str('TYPE_COLUMN_LABEL'), fullPage ? 110 : 110); + typeColumn.renderFunction = self.renderType_.bind(self); + typeColumn.headerRenderFunction = renderHeader_; + + const modTimeColumn = new cr.ui.table.TableColumn( + 'modificationTime', str('DATE_COLUMN_LABEL'), fullPage ? 150 : 210); + modTimeColumn.renderFunction = self.renderDate_.bind(self); + modTimeColumn.defaultOrder = 'desc'; + modTimeColumn.headerRenderFunction = renderHeader_; + + const columns = + [nameColumn, sizeColumn, statusColumn, typeColumn, modTimeColumn]; + + const columnModel = new FileTableColumnModel(columns); + + self.columnModel = columnModel; + + self.formatter_ = new FileMetadataFormatter(); + + const selfAsTable = /** @type {!cr.ui.Table} */ (self); + selfAsTable.setRenderFunction( + self.renderTableRow_.bind(self, selfAsTable.getRenderFunction())); + + // Keep focus on the file list when clicking on the header. + selfAsTable.header.addEventListener('mousedown', e => { + self.list.focus(); + e.preventDefault(); + }); + + self.relayoutRateLimiter_ = + new AsyncUtil.RateLimiter(self.relayoutImmediately_.bind(self)); + + // Override header#redraw to use FileTableSplitter. + /** @this {cr.ui.table.TableHeader} */ + selfAsTable.header.redraw = function() { + this.__proto__.redraw.call(this); + // Extend table splitters + const splitters = this.querySelectorAll('.table-header-splitter'); + for (let i = 0; i < splitters.length; i++) { + if (splitters[i] instanceof FileTableSplitter) { + continue; + } + FileTableSplitter.decorate(splitters[i]); + } + }; + + // Save the last selection. This is used by shouldStartDragSelection. + self.list.addEventListener('mousedown', function(e) { + this.lastSelection_ = this.selectionModel.selectedIndexes; + }.bind(self), true); + self.list.addEventListener('touchstart', function(e) { + this.lastSelection_ = this.selectionModel.selectedIndexes; + }.bind(self), true); + self.list.shouldStartDragSelection = + self.shouldStartDragSelection_.bind(self); + self.list.hasDragHitElement = self.hasDragHitElement_.bind(self); + + /** + * Obtains the index list of elements that are hit by the point or the + * rectangle. + * + * @param {number} x X coordinate value. + * @param {number} y Y coordinate value. + * @param {number=} opt_width Width of the coordinate. + * @param {number=} opt_height Height of the coordinate. + * @return {Array<number>} Index list of hit elements. + * @this {cr.ui.List} + */ + self.list.getHitElements = function(x, y, opt_width, opt_height) { + const currentSelection = []; + const bottom = y + (opt_height || 0); + for (let i = 0; i < this.selectionModel_.length; i++) { + const itemMetrics = this.getHeightsForIndex(i); + if (itemMetrics.top < bottom && + itemMetrics.top + itemMetrics.height >= y) { + currentSelection.push(i); + } + } + return currentSelection; + }; + } + + /** + * Updates high priority range of list thumbnail loader based on current + * viewport. + * + * @param {number} beginIndex Begin index. + * @param {number} endIndex End index. + * @private + */ + updateHighPriorityRange_(beginIndex, endIndex) { + // Keep these values to set range when a new list thumbnail loader is set. + this.beginIndex_ = beginIndex; + this.endIndex_ = endIndex; + + if (this.listThumbnailLoader_ !== null) { + this.listThumbnailLoader_.setHighPriorityRange(beginIndex, endIndex); + } + } + + /** + * Sets list thumbnail loader. + * @param {ListThumbnailLoader} listThumbnailLoader A list thumbnail loader. + */ + setListThumbnailLoader(listThumbnailLoader) { + if (this.listThumbnailLoader_) { + this.listThumbnailLoader_.removeEventListener( + 'thumbnailLoaded', this.onThumbnailLoadedBound_); + } + + this.listThumbnailLoader_ = listThumbnailLoader; + + if (this.listThumbnailLoader_) { + this.listThumbnailLoader_.addEventListener( + 'thumbnailLoaded', this.onThumbnailLoadedBound_); + this.listThumbnailLoader_.setHighPriorityRange( + this.beginIndex_, this.endIndex_); + } + } + + /** + * Returns the element containing the thumbnail of a certain list item as + * background image. + * @param {number} index The index of the item containing the desired + * thumbnail. + * @return {?Element} The element containing the thumbnail, or null, if an + * error occurred. + */ + getThumbnail(index) { + const listItem = this.getListItemByIndex(index); + if (!listItem) { + return null; + } + const container = listItem.querySelector('.detail-thumbnail'); + if (!container) { + return null; + } + return container.querySelector('.thumbnail'); + } + + /** + * Handles thumbnail loaded event. + * @param {!Event} event An event. + * @private + */ + onThumbnailLoaded_(event) { + const listItem = this.getListItemByIndex(event.index); + if (listItem) { + const box = listItem.querySelector('.detail-thumbnail'); + if (box) { + if (event.dataUrl) { + this.setThumbnailImage_( + assertInstanceof(box, HTMLDivElement), event.dataUrl, + true /* with animation */); + } else { + this.clearThumbnailImage_(assertInstanceof(box, HTMLDivElement)); + } + } + } + } + + /** + * Adjust column width to fit its content. + * @param {number} index Index of the column to adjust width. + * @override + */ + fitColumn(index) { + const render = this.columnModel.getRenderFunction(index); + const MAXIMUM_ROWS_TO_MEASURE = 1000; + + // Create a temporaty list item, put all cells into it and measure its + // width. Then remove the item. It fits "list > *" CSS rules. + const container = this.ownerDocument.createElement('li'); + container.style.display = 'inline-block'; + container.style.textAlign = 'start'; + // The container will have width of the longest cell. + container.style.webkitBoxOrient = 'vertical'; + + // Select at most MAXIMUM_ROWS_TO_MEASURE items around visible area. + const items = this.list.getItemsInViewPort( + this.list.scrollTop, this.list.clientHeight); + const firstIndex = Math.floor( + Math.max(0, (items.last + items.first - MAXIMUM_ROWS_TO_MEASURE) / 2)); + const lastIndex = + Math.min(this.dataModel.length, firstIndex + MAXIMUM_ROWS_TO_MEASURE); + for (let i = firstIndex; i < lastIndex; i++) { + const item = this.dataModel.item(i); + const div = this.ownerDocument.createElement('div'); + div.className = 'table-row-cell'; + div.appendChild(render(item, this.columnModel.getId(index), this)); + container.appendChild(div); + } + this.list.appendChild(container); + const width = parseFloat(window.getComputedStyle(container).width); + this.list.removeChild(container); + + this.columnModel.initializeColumnPos(); + this.columnModel.setWidthAndKeepTotal(index, Math.ceil(width)); + this.columnModel.destroyColumnPos(); + } + + /** + * Sets the visibility of the cloud import status column. + * @param {boolean} visible + */ + setImportStatusVisible(visible) { + if (this.importStatusVisible_ != visible) { + this.importStatusVisible_ = visible; + this.columnModel.setVisible(this.columnModel.indexOf('status'), visible); + this.relayout(); + } + } + + /** + * Sets date and time format. + * @param {boolean} use12hourClock True if 12 hours clock, False if 24 hours. + */ + setDateTimeFormat(use12hourClock) { + this.formatter_.setDateTimeFormat(use12hourClock); + } + + /** + * Sets whether to use modificationByMeTime as "Last Modified" time. + * @param {boolean} useModificationByMeTime + */ + setUseModificationByMeTime(useModificationByMeTime) { + this.useModificationByMeTime_ = useModificationByMeTime; + } + + /** + * Returns whether the drag event is inside a file entry in the list (and not + * the background padding area). + * @param {MouseEvent} event Drag start event. + * @return {boolean} True if the mouse is over an element in the list, False + * if + * it is in the background. + */ + hasDragHitElement_(event) { + const pos = DragSelector.getScrolledPosition(this.list, event); + return this.list.getHitElements(pos.x, pos.y).length !== 0; + } + + /** + * Obtains if the drag selection should be start or not by referring the mouse + * event. + * @param {MouseEvent} event Drag start event. + * @return {boolean} True if the mouse is hit to the background of the list, + * or certain areas of the inside of the list that would start a drag + * selection. + * @private + */ + shouldStartDragSelection_(event) { + // If the shift key is pressed, it should starts drag selection. + if (event.shiftKey) { + return true; + } + + // If we're outside of the element list, start the drag selection. + if (!this.list.hasDragHitElement(event)) { + return true; + } + + // If the position values are negative, it points the out of list. + const pos = DragSelector.getScrolledPosition(this.list, event); + if (!pos) { + return false; + } + if (pos.x < 0 || pos.y < 0) { + return true; + } + + // If the item index is out of range, it should start the drag selection. + const itemHeight = this.list.measureItem().height; + // Faster alternative to Math.floor for non-negative numbers. + const itemIndex = ~~(pos.y / itemHeight); + if (itemIndex >= this.list.dataModel.length) { + return true; + } + + // If the pointed item is already selected, it should not start the drag + // selection. + if (this.lastSelection_ && this.lastSelection_.indexOf(itemIndex) !== -1) { + return false; + } + + // If the horizontal value is not hit to column, it should start the drag + // selection. + const hitColumn = this.columnModel.getHitColumn(pos.x); + if (!hitColumn) { + return true; + } + + // Check if the point is on the column contents or not. + switch (this.columnModel.columns_[hitColumn.index].id) { + case 'name': + const item = this.list.getListItemByIndex(itemIndex); + if (!item) { + return false; + } + + const spanElement = item.querySelector('.filename-label span'); + const spanRect = spanElement.getBoundingClientRect(); + // The this.list.cachedBounds_ object is set by + // DragSelector.getScrolledPosition. + if (!this.list.cachedBounds) { + return true; + } + const textRight = + spanRect.left - this.list.cachedBounds.left + spanRect.width; + return textRight <= hitColumn.hitPosition; + default: + return true; + } + } + + /** + * Render the Name column of the detail table. + * + * Invoked by cr.ui.Table when a file needs to be rendered. + * + * @param {!Entry} entry The Entry object to render. + * @param {string} columnId The id of the column to be rendered. + * @param {cr.ui.Table} table The table doing the rendering. + * @return {!HTMLDivElement} Created element. + * @private + */ + renderName_(entry, columnId, table) { + const label = /** @type {!HTMLDivElement} */ + (this.ownerDocument.createElement('div')); + + const mimeType = + this.metadataModel_.getCache([entry], ['contentMimeType'])[0] + .contentMimeType; + const locationInfo = this.volumeManager_.getLocationInfo(entry); + const icon = filelist.renderFileTypeIcon( + this.ownerDocument, entry, locationInfo, mimeType); + if (FileType.isImage(entry, mimeType) || + FileType.isVideo(entry, mimeType) || + FileType.isAudio(entry, mimeType) || FileType.isRaw(entry, mimeType)) { + icon.appendChild(this.renderThumbnail_(entry)); + } + icon.appendChild(this.renderCheckmark_()); + label.appendChild(icon); + + label.entry = entry; + label.className = 'detail-name'; + label.appendChild( + filelist.renderFileNameLabel(this.ownerDocument, entry, locationInfo)); + return label; + } + + /** + * Render the Size column of the detail table. + * + * @param {Entry} entry The Entry object to render. + * @param {string} columnId The id of the column to be rendered. + * @param {cr.ui.Table} table The table doing the rendering. + * @return {!HTMLDivElement} Created element. + * @private + */ + renderSize_(entry, columnId, table) { + const div = /** @type {!HTMLDivElement} */ + (this.ownerDocument.createElement('div')); + div.className = 'size'; + this.updateSize_(div, entry); + + return div; + } + + /** + * Sets up or updates the size cell. + * + * @param {HTMLDivElement} div The table cell. + * @param {Entry} entry The corresponding entry. + * @private + */ + updateSize_(div, entry) { + const metadata = + this.metadataModel_.getCache([entry], ['size', 'hosted'])[0]; + const size = metadata.size; + const hosted = metadata.hosted; + div.textContent = this.formatter_.formatSize(size, hosted); + } + + /** + * Render the Status column of the detail table. + * + * @param {Entry} entry The Entry object to render. + * @param {string} columnId The id of the column to be rendered. + * @param {cr.ui.Table} table The table doing the rendering. + * @return {!HTMLDivElement} Created element. + * @private + */ + renderStatus_(entry, columnId, table) { + const div = + /** @type {!HTMLDivElement} */ ( + this.ownerDocument.createElement('div')); + div.className = 'status status-icon'; + if (entry) { + this.updateStatus_(div, entry); + } + + return div; + } + + /** + * Returns the status of the entry w.r.t. the given import destination. + * @param {Entry} entry + * @param {!importer.Destination} destination + * @return {!Promise<string>} The import status - will be 'imported', + * 'copied', or 'unknown'. + */ + getImportStatus_(entry, destination) { + // If import status is not visible, early out because there's no point + // retrieving it. + if (!this.importStatusVisible_ || !importer.isEligibleType(entry)) { + // Our import history doesn't deal with directories. + // TODO(kenobi): May need to revisit this if the above assumption changes. + return Promise.resolve('unknown'); + } + // For the compiler. + const fileEntry = /** @type {!FileEntry} */ (entry); + + return this.historyLoader_.getHistory() + .then( + /** @param {!importer.ImportHistory} history */ + history => { + return Promise.all([ + history.wasImported(fileEntry, destination), + history.wasCopied(fileEntry, destination) + ]); + }) + .then( + /** @param {!Array<boolean>} status */ + status => { + if (status[0]) { + return 'imported'; + } else if (status[1]) { + return 'copied'; + } else { + return 'unknown'; + } + }); + } + + /** + * Render the status icon of the detail table. + * + * @param {HTMLDivElement} div + * @param {Entry} entry The Entry object to render. + * @private + */ + updateStatus_(div, entry) { + this.getImportStatus_(entry, importer.Destination.GOOGLE_DRIVE) + .then( + /** @param {string} status */ + status => { + div.setAttribute('file-status-icon', status); + }); + } + + /** + * Render the Type column of the detail table. + * + * @param {Entry} entry The Entry object to render. + * @param {string} columnId The id of the column to be rendered. + * @param {cr.ui.Table} table The table doing the rendering. + * @return {!HTMLDivElement} Created element. + * @private + */ + renderType_(entry, columnId, table) { + const div = /** @type {!HTMLDivElement} */ + (this.ownerDocument.createElement('div')); + div.className = 'type'; + + const mimeType = + this.metadataModel_.getCache([entry], ['contentMimeType'])[0] + .contentMimeType; + div.textContent = + FileListModel.getFileTypeString(FileType.getType(entry, mimeType)); + + // For removable partitions, display file system type. + if (!mimeType && entry.volumeInfo && entry.volumeInfo.diskFileSystemType) { + div.textContent = entry.volumeInfo.diskFileSystemType; + } + + return div; + } + + /** + * Render the Date column of the detail table. + * + * @param {Entry} entry The Entry object to render. + * @param {string} columnId The id of the column to be rendered. + * @param {cr.ui.Table} table The table doing the rendering. + * @return {HTMLDivElement} Created element. + * @private + */ + renderDate_(entry, columnId, table) { + const div = /** @type {!HTMLDivElement} */ + (this.ownerDocument.createElement('div')); + div.className = 'date'; + + this.updateDate_(div, entry); + return div; + } + + /** + * Sets up or updates the date cell. + * + * @param {HTMLDivElement} div The table cell. + * @param {Entry} entry Entry of file to update. + * @private + */ + updateDate_(div, entry) { + // For now, Team Drive roots have the incorrect modified date value. Hide it + // until we get the proper one (see https://crbug.com/861622). + if (util.isTeamDriveRoot(entry)) { + div.textContent = '--'; + return; + } + + const item = this.metadataModel_.getCache( + [entry], ['modificationTime', 'modificationByMeTime'])[0]; + const modTime = this.useModificationByMeTime_ ? + item.modificationByMeTime || item.modificationTime || null : + item.modificationTime || null; + + div.textContent = this.formatter_.formatModDate(modTime); + } + + /** + * Updates the file metadata in the table item. + * + * @param {Element} item Table item. + * @param {Entry} entry File entry. + */ + updateFileMetadata(item, entry) { + this.updateDate_( + /** @type {!HTMLDivElement} */ (item.querySelector('.date')), entry); + this.updateSize_( + /** @type {!HTMLDivElement} */ (item.querySelector('.size')), entry); + this.updateStatus_( + /** @type {!HTMLDivElement} */ (item.querySelector('.status')), entry); + } + + /** + * Updates list items 'in place' on metadata change. + * @param {string} type Type of metadata change. + * @param {Array<Entry>} entries Entries to update. + */ + updateListItemsMetadata(type, entries) { + const urls = util.entriesToURLs(entries); + const forEachCell = (selector, callback) => { + const cells = this.querySelectorAll(selector); + for (let i = 0; i < cells.length; i++) { + const cell = /** @type {HTMLElement} */ (cells[i]); + const listItem = this.list_.getListItemAncestor(cell); + const entry = this.dataModel.item(listItem.listIndex); + if (entry && urls.indexOf(entry.toURL()) !== -1) { + callback.call(this, cell, entry, listItem); + } + } + }; + if (type === 'filesystem') { + forEachCell('.table-row-cell > .date', function(item, entry, unused) { + this.updateDate_(item, entry); + }); + forEachCell('.table-row-cell > .size', function(item, entry, unused) { + this.updateSize_(item, entry); + }); + } else if (type === 'external') { + // The cell name does not matter as the entire list item is needed. + forEachCell('.table-row-cell > .date', function(item, entry, listItem) { + filelist.updateListItemExternalProps( + listItem, + this.metadataModel_.getCache( + [entry], + [ + 'availableOffline', 'customIconUrl', 'shared', + 'isMachineRoot', 'isExternalMedia', 'hosted' + ])[0], + util.isTeamDriveRoot(entry)); + }); + } else if (type === 'import-history') { + forEachCell('.table-row-cell > .status', function(item, entry, unused) { + this.updateStatus_(item, entry); + }); + } + } + + /** + * Renders table row. + * @param {function(Entry, cr.ui.Table)} baseRenderFunction Base renderer. + * @param {Entry} entry Corresponding entry. + * @return {HTMLLIElement} Created element. + * @private + */ + renderTableRow_(baseRenderFunction, entry) { + const item = baseRenderFunction(entry, this); + const nameId = item.id + '-entry-name'; + const sizeId = item.id + '-size'; + const dateId = item.id + '-date'; + filelist.decorateListItem(item, entry, assert(this.metadataModel_)); + item.setAttribute('file-name', entry.name); + item.querySelector('.entry-name').setAttribute('id', nameId); + item.querySelector('.size').setAttribute('id', sizeId); + item.querySelector('.date').setAttribute('id', dateId); + item.setAttribute('aria-labelledby', nameId + ' ' + sizeId + ' ' + dateId); + return item; + } + + /** + * Renders the file thumbnail in the detail table. + * @param {Entry} entry The Entry object to render. + * @return {!HTMLDivElement} Created element. + * @private + */ + renderThumbnail_(entry) { + const box = /** @type {!HTMLDivElement} */ + (this.ownerDocument.createElement('div')); + box.className = 'detail-thumbnail'; + + // Set thumbnail if it's already in cache. + const thumbnailData = this.listThumbnailLoader_ ? + this.listThumbnailLoader_.getThumbnailFromCache(entry) : + null; + if (thumbnailData && thumbnailData.dataUrl) { + this.setThumbnailImage_( + box, thumbnailData.dataUrl, false /* without animation */); + } + + return box; + } + + /** + * Sets thumbnail image to the box. + * @param {!HTMLDivElement} box Detail thumbnail div element. + * @param {string} dataUrl Data url of thumbnail. + * @param {boolean} shouldAnimate Whether the thumbnail is shown with + * animation or not. + * @private + */ + setThumbnailImage_(box, dataUrl, shouldAnimate) { + const oldThumbnails = box.querySelectorAll('.thumbnail'); + + const thumbnail = box.ownerDocument.createElement('div'); + thumbnail.classList.add('thumbnail'); + thumbnail.style.backgroundImage = 'url(' + dataUrl + ')'; + thumbnail.addEventListener('animationend', () => { + // Remove animation css once animation is completed in order not to + // animate again when an item is attached to the dom again. + thumbnail.classList.remove('animate'); + + for (let i = 0; i < oldThumbnails.length; i++) { + if (box.contains(oldThumbnails[i])) { + box.removeChild(oldThumbnails[i]); + } + } + }); + + if (shouldAnimate) { + thumbnail.classList.add('animate'); + } + + box.appendChild(thumbnail); + } + + /** + * Clears thumbnail image from the box. + * @param {!HTMLDivElement} box Detail thumbnail div element. + * @private + */ + clearThumbnailImage_(box) { + const oldThumbnails = box.querySelectorAll('.thumbnail'); + + for (let i = 0; i < oldThumbnails.length; i++) { + box.removeChild(oldThumbnails[i]); + } + } + + /** + * Renders the selection checkmark in the detail table. + * @return {!HTMLDivElement} Created element. + * @private + */ + renderCheckmark_() { + const checkmark = /** @type {!HTMLDivElement} */ + (this.ownerDocument.createElement('div')); + checkmark.className = 'detail-checkmark'; + return checkmark; + } + + /** + * Redraws the UI. Skips multiple consecutive calls. + */ + relayout() { + this.relayoutRateLimiter_.run(); + } + + /** + * Redraws the UI immediately. + * @private + */ + relayoutImmediately_() { + if (this.clientWidth > 0) { + this.normalizeColumns(); + } + this.redraw(); + cr.dispatchSimpleEvent(this.list, 'relayout'); + } } /** * Inherits from cr.ui.Table. */ FileTable.prototype.__proto__ = cr.ui.Table.prototype; - -/** - * Decorates the element. - * @param {!Element} self Table to decorate. - * @param {!MetadataModel} metadataModel To retrieve - * metadata. - * @param {!VolumeManager} volumeManager To retrieve volume info. - * @param {!importer.HistoryLoader} historyLoader - * @param {boolean} fullPage True if it's full page File Manager, - * False if a file open/save dialog. - */ -FileTable.decorate = - (self, metadataModel, volumeManager, historyLoader, fullPage) => { - cr.ui.Table.decorate(self); - self.__proto__ = FileTable.prototype; - FileTableList.decorate(self.list); - self.list.setOnMergeItems(self.updateHighPriorityRange_.bind(self)); - self.metadataModel_ = metadataModel; - self.volumeManager_ = volumeManager; - self.historyLoader_ = historyLoader; - - /** @private {ListThumbnailLoader} */ - self.listThumbnailLoader_ = null; - - /** @private {number} */ - self.beginIndex_ = 0; - - /** @private {number} */ - self.endIndex_ = 0; - - /** @private {function(!Event)} */ - self.onThumbnailLoadedBound_ = self.onThumbnailLoaded_.bind(self); - - /** - * Reflects the visibility of import status in the UI. Assumption: import - * status is only enabled in import-eligible locations. See - * ImportController#onDirectoryChanged. For this reason, the code in this - * class checks if import status is visible, and if so, assumes that all - * the files are in an import-eligible location. - * TODO(kenobi): Clean this up once import status is queryable from - * metadata. - * - * @private {boolean} - */ - self.importStatusVisible_ = true; - - /** @private {boolean} */ - self.useModificationByMeTime_ = false; - - const nameColumn = new cr.ui.table.TableColumn( - 'name', str('NAME_COLUMN_LABEL'), fullPage ? 386 : 324); - nameColumn.renderFunction = self.renderName_.bind(self); - nameColumn.headerRenderFunction = renderHeader_; - - const sizeColumn = new cr.ui.table.TableColumn( - 'size', str('SIZE_COLUMN_LABEL'), 110, true); - sizeColumn.renderFunction = self.renderSize_.bind(self); - sizeColumn.defaultOrder = 'desc'; - sizeColumn.headerRenderFunction = renderHeader_; - - const statusColumn = new cr.ui.table.TableColumn( - 'status', str('STATUS_COLUMN_LABEL'), 60, true); - statusColumn.renderFunction = self.renderStatus_.bind(self); - statusColumn.visible = self.importStatusVisible_; - statusColumn.headerRenderFunction = renderHeader_; - - const typeColumn = new cr.ui.table.TableColumn( - 'type', str('TYPE_COLUMN_LABEL'), fullPage ? 110 : 110); - typeColumn.renderFunction = self.renderType_.bind(self); - typeColumn.headerRenderFunction = renderHeader_; - - const modTimeColumn = new cr.ui.table.TableColumn( - 'modificationTime', str('DATE_COLUMN_LABEL'), fullPage ? 150 : 210); - modTimeColumn.renderFunction = self.renderDate_.bind(self); - modTimeColumn.defaultOrder = 'desc'; - modTimeColumn.headerRenderFunction = renderHeader_; - - const columns = - [nameColumn, sizeColumn, statusColumn, typeColumn, modTimeColumn]; - - const columnModel = new FileTableColumnModel(columns); - - self.columnModel = columnModel; - - self.formatter_ = new FileMetadataFormatter(); - - const selfAsTable = /** @type {!cr.ui.Table} */ (self); - selfAsTable.setRenderFunction( - self.renderTableRow_.bind(self, selfAsTable.getRenderFunction())); - - // Keep focus on the file list when clicking on the header. - selfAsTable.header.addEventListener('mousedown', e => { - self.list.focus(); - e.preventDefault(); - }); - - self.relayoutRateLimiter_ = - new AsyncUtil.RateLimiter(self.relayoutImmediately_.bind(self)); - - // Override header#redraw to use FileTableSplitter. - /** @this {cr.ui.table.TableHeader} */ - selfAsTable.header.redraw = function() { - this.__proto__.redraw.call(this); - // Extend table splitters - const splitters = this.querySelectorAll('.table-header-splitter'); - for (let i = 0; i < splitters.length; i++) { - if (splitters[i] instanceof FileTableSplitter) { - continue; - } - FileTableSplitter.decorate(splitters[i]); - } - }; - - // Save the last selection. This is used by shouldStartDragSelection. - self.list.addEventListener('mousedown', function(e) { - this.lastSelection_ = this.selectionModel.selectedIndexes; - }.bind(self), true); - self.list.addEventListener('touchstart', function(e) { - this.lastSelection_ = this.selectionModel.selectedIndexes; - }.bind(self), true); - self.list.shouldStartDragSelection = - self.shouldStartDragSelection_.bind(self); - self.list.hasDragHitElement = self.hasDragHitElement_.bind(self); - - /** - * Obtains the index list of elements that are hit by the point or the - * rectangle. - * - * @param {number} x X coordinate value. - * @param {number} y Y coordinate value. - * @param {number=} opt_width Width of the coordinate. - * @param {number=} opt_height Height of the coordinate. - * @return {Array<number>} Index list of hit elements. - * @this {cr.ui.List} - */ - self.list.getHitElements = function(x, y, opt_width, opt_height) { - const currentSelection = []; - const bottom = y + (opt_height || 0); - for (let i = 0; i < this.selectionModel_.length; i++) { - const itemMetrics = this.getHeightsForIndex(i); - if (itemMetrics.top < bottom && - itemMetrics.top + itemMetrics.height >= y) { - currentSelection.push(i); - } - } - return currentSelection; - }; - }; - -/** - * Updates high priority range of list thumbnail loader based on current - * viewport. - * - * @param {number} beginIndex Begin index. - * @param {number} endIndex End index. - * @private - */ -FileTable.prototype.updateHighPriorityRange_ = function(beginIndex, endIndex) { - // Keep these values to set range when a new list thumbnail loader is set. - this.beginIndex_ = beginIndex; - this.endIndex_ = endIndex; - - if (this.listThumbnailLoader_ !== null) { - this.listThumbnailLoader_.setHighPriorityRange(beginIndex, endIndex); - } -}; - -/** - * Sets list thumbnail loader. - * @param {ListThumbnailLoader} listThumbnailLoader A list thumbnail loader. - */ -FileTable.prototype.setListThumbnailLoader = function(listThumbnailLoader) { - if (this.listThumbnailLoader_) { - this.listThumbnailLoader_.removeEventListener( - 'thumbnailLoaded', this.onThumbnailLoadedBound_); - } - - this.listThumbnailLoader_ = listThumbnailLoader; - - if (this.listThumbnailLoader_) { - this.listThumbnailLoader_.addEventListener( - 'thumbnailLoaded', this.onThumbnailLoadedBound_); - this.listThumbnailLoader_.setHighPriorityRange( - this.beginIndex_, this.endIndex_); - } -}; - -/** - * Returns the element containing the thumbnail of a certain list item as - * background image. - * @param {number} index The index of the item containing the desired thumbnail. - * @return {?Element} The element containing the thumbnail, or null, if an error - * occurred. - */ -FileTable.prototype.getThumbnail = function(index) { - const listItem = this.getListItemByIndex(index); - if (!listItem) { - return null; - } - const container = listItem.querySelector('.detail-thumbnail'); - if (!container) { - return null; - } - return container.querySelector('.thumbnail'); -}; - -/** - * Handles thumbnail loaded event. - * @param {!Event} event An event. - * @private - */ -FileTable.prototype.onThumbnailLoaded_ = function(event) { - const listItem = this.getListItemByIndex(event.index); - if (listItem) { - const box = listItem.querySelector('.detail-thumbnail'); - if (box) { - if (event.dataUrl) { - this.setThumbnailImage_( - assertInstanceof(box, HTMLDivElement), event.dataUrl, - true /* with animation */); - } else { - this.clearThumbnailImage_(assertInstanceof(box, HTMLDivElement)); - } - } - } -}; - -/** - * Adjust column width to fit its content. - * @param {number} index Index of the column to adjust width. - * @override - */ -FileTable.prototype.fitColumn = function(index) { - const render = this.columnModel.getRenderFunction(index); - const MAXIMUM_ROWS_TO_MEASURE = 1000; - - // Create a temporaty list item, put all cells into it and measure its - // width. Then remove the item. It fits "list > *" CSS rules. - const container = this.ownerDocument.createElement('li'); - container.style.display = 'inline-block'; - container.style.textAlign = 'start'; - // The container will have width of the longest cell. - container.style.webkitBoxOrient = 'vertical'; - - // Select at most MAXIMUM_ROWS_TO_MEASURE items around visible area. - const items = - this.list.getItemsInViewPort(this.list.scrollTop, this.list.clientHeight); - const firstIndex = Math.floor( - Math.max(0, (items.last + items.first - MAXIMUM_ROWS_TO_MEASURE) / 2)); - const lastIndex = - Math.min(this.dataModel.length, firstIndex + MAXIMUM_ROWS_TO_MEASURE); - for (let i = firstIndex; i < lastIndex; i++) { - const item = this.dataModel.item(i); - const div = this.ownerDocument.createElement('div'); - div.className = 'table-row-cell'; - div.appendChild(render(item, this.columnModel.getId(index), this)); - container.appendChild(div); - } - this.list.appendChild(container); - const width = parseFloat(window.getComputedStyle(container).width); - this.list.removeChild(container); - - this.columnModel.initializeColumnPos(); - this.columnModel.setWidthAndKeepTotal(index, Math.ceil(width)); - this.columnModel.destroyColumnPos(); -}; - -/** - * Sets the visibility of the cloud import status column. - * @param {boolean} visible - */ -FileTable.prototype.setImportStatusVisible = function(visible) { - if (this.importStatusVisible_ != visible) { - this.importStatusVisible_ = visible; - this.columnModel.setVisible(this.columnModel.indexOf('status'), visible); - this.relayout(); - } -}; - -/** - * Sets date and time format. - * @param {boolean} use12hourClock True if 12 hours clock, False if 24 hours. - */ -FileTable.prototype.setDateTimeFormat = function(use12hourClock) { - this.formatter_.setDateTimeFormat(use12hourClock); -}; - -/** - * Sets whether to use modificationByMeTime as "Last Modified" time. - * @param {boolean} useModificationByMeTime - */ -FileTable.prototype.setUseModificationByMeTime = function( - useModificationByMeTime) { - this.useModificationByMeTime_ = useModificationByMeTime; -}; - -/** - * Returns whether the drag event is inside a file entry in the list (and not - * the background padding area). - * @param {MouseEvent} event Drag start event. - * @return {boolean} True if the mouse is over an element in the list, False if - * it is in the background. - */ -FileTable.prototype.hasDragHitElement_ = function(event) { - const pos = DragSelector.getScrolledPosition(this.list, event); - return this.list.getHitElements(pos.x, pos.y).length !== 0; -}; - -/** - * Obtains if the drag selection should be start or not by referring the mouse - * event. - * @param {MouseEvent} event Drag start event. - * @return {boolean} True if the mouse is hit to the background of the list, or - * certain areas of the inside of the list that would start a - * drag selection. - * @private - */ -FileTable.prototype.shouldStartDragSelection_ = function(event) { - // If the shift key is pressed, it should starts drag selection. - if (event.shiftKey) { - return true; - } - - // If we're outside of the element list, start the drag selection. - if (!this.list.hasDragHitElement(event)) { - return true; - } - - // If the position values are negative, it points the out of list. - const pos = DragSelector.getScrolledPosition(this.list, event); - if (!pos) { - return false; - } - if (pos.x < 0 || pos.y < 0) { - return true; - } - - // If the item index is out of range, it should start the drag selection. - const itemHeight = this.list.measureItem().height; - // Faster alternative to Math.floor for non-negative numbers. - const itemIndex = ~~(pos.y / itemHeight); - if (itemIndex >= this.list.dataModel.length) { - return true; - } - - // If the pointed item is already selected, it should not start the drag - // selection. - if (this.lastSelection_ && this.lastSelection_.indexOf(itemIndex) !== -1) { - return false; - } - - // If the horizontal value is not hit to column, it should start the drag - // selection. - const hitColumn = this.columnModel.getHitColumn(pos.x); - if (!hitColumn) { - return true; - } - - // Check if the point is on the column contents or not. - switch (this.columnModel.columns_[hitColumn.index].id) { - case 'name': - const item = this.list.getListItemByIndex(itemIndex); - if (!item) { - return false; - } - - const spanElement = item.querySelector('.filename-label span'); - const spanRect = spanElement.getBoundingClientRect(); - // The this.list.cachedBounds_ object is set by - // DragSelector.getScrolledPosition. - if (!this.list.cachedBounds) { - return true; - } - const textRight = - spanRect.left - this.list.cachedBounds.left + spanRect.width; - return textRight <= hitColumn.hitPosition; - default: - return true; - } -}; - -/** - * Render the Name column of the detail table. - * - * Invoked by cr.ui.Table when a file needs to be rendered. - * - * @param {!Entry} entry The Entry object to render. - * @param {string} columnId The id of the column to be rendered. - * @param {cr.ui.Table} table The table doing the rendering. - * @return {!HTMLDivElement} Created element. - * @private - */ -FileTable.prototype.renderName_ = function(entry, columnId, table) { - const label = /** @type {!HTMLDivElement} */ - (this.ownerDocument.createElement('div')); - - const mimeType = this.metadataModel_.getCache([entry], ['contentMimeType'])[0] - .contentMimeType; - const locationInfo = this.volumeManager_.getLocationInfo(entry); - const icon = filelist.renderFileTypeIcon( - this.ownerDocument, entry, locationInfo, mimeType); - if (FileType.isImage(entry, mimeType) || FileType.isVideo(entry, mimeType) || - FileType.isAudio(entry, mimeType) || FileType.isRaw(entry, mimeType)) { - icon.appendChild(this.renderThumbnail_(entry)); - } - icon.appendChild(this.renderCheckmark_()); - label.appendChild(icon); - - label.entry = entry; - label.className = 'detail-name'; - label.appendChild( - filelist.renderFileNameLabel(this.ownerDocument, entry, locationInfo)); - return label; -}; - -/** - * Render the Size column of the detail table. - * - * @param {Entry} entry The Entry object to render. - * @param {string} columnId The id of the column to be rendered. - * @param {cr.ui.Table} table The table doing the rendering. - * @return {!HTMLDivElement} Created element. - * @private - */ -FileTable.prototype.renderSize_ = function(entry, columnId, table) { - const div = /** @type {!HTMLDivElement} */ - (this.ownerDocument.createElement('div')); - div.className = 'size'; - this.updateSize_(div, entry); - - return div; -}; - -/** - * Sets up or updates the size cell. - * - * @param {HTMLDivElement} div The table cell. - * @param {Entry} entry The corresponding entry. - * @private - */ -FileTable.prototype.updateSize_ = function(div, entry) { - const metadata = this.metadataModel_.getCache([entry], ['size', 'hosted'])[0]; - const size = metadata.size; - const hosted = metadata.hosted; - div.textContent = this.formatter_.formatSize(size, hosted); -}; - -/** - * Render the Status column of the detail table. - * - * @param {Entry} entry The Entry object to render. - * @param {string} columnId The id of the column to be rendered. - * @param {cr.ui.Table} table The table doing the rendering. - * @return {!HTMLDivElement} Created element. - * @private - */ -FileTable.prototype.renderStatus_ = function(entry, columnId, table) { - const div = - /** @type {!HTMLDivElement} */ (this.ownerDocument.createElement('div')); - div.className = 'status status-icon'; - if (entry) { - this.updateStatus_(div, entry); - } - - return div; -}; - -/** - * Returns the status of the entry w.r.t. the given import destination. - * @param {Entry} entry - * @param {!importer.Destination} destination - * @return {!Promise<string>} The import status - will be 'imported', 'copied', - * or 'unknown'. - */ -FileTable.prototype.getImportStatus_ = function(entry, destination) { - // If import status is not visible, early out because there's no point - // retrieving it. - if (!this.importStatusVisible_ || !importer.isEligibleType(entry)) { - // Our import history doesn't deal with directories. - // TODO(kenobi): May need to revisit this if the above assumption changes. - return Promise.resolve('unknown'); - } - // For the compiler. - const fileEntry = /** @type {!FileEntry} */ (entry); - - return this.historyLoader_.getHistory() - .then( - /** @param {!importer.ImportHistory} history */ - history => { - return Promise.all([ - history.wasImported(fileEntry, destination), - history.wasCopied(fileEntry, destination) - ]); - }) - .then( - /** @param {!Array<boolean>} status */ - status => { - if (status[0]) { - return 'imported'; - } else if (status[1]) { - return 'copied'; - } else { - return 'unknown'; - } - }); -}; - -/** - * Render the status icon of the detail table. - * - * @param {HTMLDivElement} div - * @param {Entry} entry The Entry object to render. - * @private - */ -FileTable.prototype.updateStatus_ = function(div, entry) { - this.getImportStatus_(entry, importer.Destination.GOOGLE_DRIVE) - .then( - /** @param {string} status */ - status => { - div.setAttribute('file-status-icon', status); - }); -}; - -/** - * Render the Type column of the detail table. - * - * @param {Entry} entry The Entry object to render. - * @param {string} columnId The id of the column to be rendered. - * @param {cr.ui.Table} table The table doing the rendering. - * @return {!HTMLDivElement} Created element. - * @private - */ -FileTable.prototype.renderType_ = function(entry, columnId, table) { - const div = /** @type {!HTMLDivElement} */ - (this.ownerDocument.createElement('div')); - div.className = 'type'; - - const mimeType = this.metadataModel_.getCache([entry], ['contentMimeType'])[0] - .contentMimeType; - div.textContent = - FileListModel.getFileTypeString(FileType.getType(entry, mimeType)); - - // For removable partitions, display file system type. - if (!mimeType && entry.volumeInfo && entry.volumeInfo.diskFileSystemType) { - div.textContent = entry.volumeInfo.diskFileSystemType; - } - - return div; -}; - -/** - * Render the Date column of the detail table. - * - * @param {Entry} entry The Entry object to render. - * @param {string} columnId The id of the column to be rendered. - * @param {cr.ui.Table} table The table doing the rendering. - * @return {HTMLDivElement} Created element. - * @private - */ -FileTable.prototype.renderDate_ = function(entry, columnId, table) { - const div = /** @type {!HTMLDivElement} */ - (this.ownerDocument.createElement('div')); - div.className = 'date'; - - this.updateDate_(div, entry); - return div; -}; - -/** - * Sets up or updates the date cell. - * - * @param {HTMLDivElement} div The table cell. - * @param {Entry} entry Entry of file to update. - * @private - */ -FileTable.prototype.updateDate_ = function(div, entry) { - // For now, Team Drive roots have the incorrect modified date value. Hide it - // until we get the proper one (see https://crbug.com/861622). - if (util.isTeamDriveRoot(entry)) { - div.textContent = '--'; - return; - } - - const item = this.metadataModel_.getCache( - [entry], ['modificationTime', 'modificationByMeTime'])[0]; - const modTime = this.useModificationByMeTime_ ? - item.modificationByMeTime || item.modificationTime : - item.modificationTime; - - div.textContent = this.formatter_.formatModDate(modTime); -}; - -/** - * Updates the file metadata in the table item. - * - * @param {Element} item Table item. - * @param {Entry} entry File entry. - */ -FileTable.prototype.updateFileMetadata = function(item, entry) { - this.updateDate_( - /** @type {!HTMLDivElement} */ (item.querySelector('.date')), entry); - this.updateSize_( - /** @type {!HTMLDivElement} */ (item.querySelector('.size')), entry); - this.updateStatus_( - /** @type {!HTMLDivElement} */ (item.querySelector('.status')), entry); -}; - -/** - * Updates list items 'in place' on metadata change. - * @param {string} type Type of metadata change. - * @param {Array<Entry>} entries Entries to update. - */ -FileTable.prototype.updateListItemsMetadata = function(type, entries) { - const urls = util.entriesToURLs(entries); - const forEachCell = (selector, callback) => { - const cells = this.querySelectorAll(selector); - for (let i = 0; i < cells.length; i++) { - const cell = cells[i]; - const listItem = this.list_.getListItemAncestor(cell); - const entry = this.dataModel.item(listItem.listIndex); - if (entry && urls.indexOf(entry.toURL()) !== -1) { - callback.call(this, cell, entry, listItem); - } - } - }; - if (type === 'filesystem') { - forEachCell('.table-row-cell > .date', function(item, entry, unused) { - this.updateDate_(item, entry); - }); - forEachCell('.table-row-cell > .size', function(item, entry, unused) { - this.updateSize_(item, entry); - }); - } else if (type === 'external') { - // The cell name does not matter as the entire list item is needed. - forEachCell('.table-row-cell > .date', function(item, entry, listItem) { - filelist.updateListItemExternalProps( - listItem, - this.metadataModel_.getCache( - [entry], - [ - 'availableOffline', 'customIconUrl', 'shared', 'isMachineRoot', - 'isExternalMedia', 'hosted' - ])[0], - util.isTeamDriveRoot(entry)); - }); - } else if (type === 'import-history') { - forEachCell('.table-row-cell > .status', function(item, entry, unused) { - this.updateStatus_(item, entry); - }); - } -}; - -/** - * Renders table row. - * @param {function(Entry, cr.ui.Table)} baseRenderFunction Base renderer. - * @param {Entry} entry Corresponding entry. - * @return {HTMLLIElement} Created element. - * @private - */ -FileTable.prototype.renderTableRow_ = function(baseRenderFunction, entry) { - const item = baseRenderFunction(entry, this); - const nameId = item.id + '-entry-name'; - const sizeId = item.id + '-size'; - const dateId = item.id + '-date'; - filelist.decorateListItem(item, entry, this.metadataModel_); - item.setAttribute('file-name', entry.name); - item.querySelector('.entry-name').setAttribute('id', nameId); - item.querySelector('.size').setAttribute('id', sizeId); - item.querySelector('.date').setAttribute('id', dateId); - item.setAttribute('aria-labelledby', nameId + ' ' + sizeId + ' ' + dateId); - return item; -}; - -/** - * Renders the file thumbnail in the detail table. - * @param {Entry} entry The Entry object to render. - * @return {!HTMLDivElement} Created element. - * @private - */ -FileTable.prototype.renderThumbnail_ = function(entry) { - const box = /** @type {!HTMLDivElement} */ - (this.ownerDocument.createElement('div')); - box.className = 'detail-thumbnail'; - - // Set thumbnail if it's already in cache. - const thumbnailData = this.listThumbnailLoader_ ? - this.listThumbnailLoader_.getThumbnailFromCache(entry) : - null; - if (thumbnailData && thumbnailData.dataUrl) { - this.setThumbnailImage_( - box, this.listThumbnailLoader_.getThumbnailFromCache(entry).dataUrl, - false /* without animation */); - } - - return box; -}; - -/** - * Sets thumbnail image to the box. - * @param {!HTMLDivElement} box Detail thumbnail div element. - * @param {string} dataUrl Data url of thumbnail. - * @param {boolean} shouldAnimate Whether the thumbnail is shown with animation - * or not. - * @private - */ -FileTable.prototype.setThumbnailImage_ = (box, dataUrl, shouldAnimate) => { - const oldThumbnails = box.querySelectorAll('.thumbnail'); - - const thumbnail = box.ownerDocument.createElement('div'); - thumbnail.classList.add('thumbnail'); - thumbnail.style.backgroundImage = 'url(' + dataUrl + ')'; - thumbnail.addEventListener('animationend', () => { - // Remove animation css once animation is completed in order not to animate - // again when an item is attached to the dom again. - thumbnail.classList.remove('animate'); - - for (let i = 0; i < oldThumbnails.length; i++) { - if (box.contains(oldThumbnails[i])) { - box.removeChild(oldThumbnails[i]); - } - } - }); - - if (shouldAnimate) { - thumbnail.classList.add('animate'); - } - - box.appendChild(thumbnail); -}; - -/** - * Clears thumbnail image from the box. - * @param {!HTMLDivElement} box Detail thumbnail div element. - * @private - */ -FileTable.prototype.clearThumbnailImage_ = box => { - const oldThumbnails = box.querySelectorAll('.thumbnail'); - - for (let i = 0; i < oldThumbnails.length; i++) { - box.removeChild(oldThumbnails[i]); - } -}; - -/** - * Renders the selection checkmark in the detail table. - * @return {!HTMLDivElement} Created element. - * @private - */ -FileTable.prototype.renderCheckmark_ = function() { - const checkmark = /** @type {!HTMLDivElement} */ - (this.ownerDocument.createElement('div')); - checkmark.className = 'detail-checkmark'; - return checkmark; -}; - -/** - * Redraws the UI. Skips multiple consecutive calls. - */ -FileTable.prototype.relayout = function() { - this.relayoutRateLimiter_.run(); -}; - -/** - * Redraws the UI immediately. - * @private - */ -FileTable.prototype.relayoutImmediately_ = function() { - if (this.clientWidth > 0) { - this.normalizeColumns(); - } - this.redraw(); - cr.dispatchSimpleEvent(this.list, 'relayout'); -};
diff --git a/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog.js b/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog.js index 17b7ab9..9ccdc93c 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog.js +++ b/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog.js
@@ -8,181 +8,178 @@ cr.define('cr.filebrowser', () => { /** * Creates dialog in DOM tree. - * - * @param {HTMLElement} parentNode Node to be parent for this dialog. - * @constructor - * @extends {FileManagerDialogBase} */ - function InstallLinuxPackageDialog(parentNode) { - FileManagerDialogBase.call(this, parentNode); + class InstallLinuxPackageDialog extends FileManagerDialogBase { + /** + * @param {HTMLElement} parentNode Node to be parent for this dialog. + */ + constructor(parentNode) { + super(parentNode); - this.frame_.id = 'install-linux-package-dialog'; + this.frame_.id = 'install-linux-package-dialog'; - this.details_frame_ = this.document_.createElement('div'); - this.details_frame_.className = 'install-linux-package-details-frame'; - this.frame_.insertBefore(this.details_frame_, this.buttons); + this.details_frame_ = this.document_.createElement('div'); + this.details_frame_.className = 'install-linux-package-details-frame'; + this.frame_.insertBefore(this.details_frame_, this.buttons); - this.details_label_ = this.document_.createElement('div'); - this.details_label_.className = 'install-linux-package-details-label'; - this.details_label_.textContent = - str('INSTALL_LINUX_PACKAGE_DETAILS_LABEL'); + this.details_label_ = this.document_.createElement('div'); + this.details_label_.className = 'install-linux-package-details-label'; + this.details_label_.textContent = + str('INSTALL_LINUX_PACKAGE_DETAILS_LABEL'); - // The OK button normally dismisses the dialog, so add a button we can - // customize. - this.installButton_ = this.okButton_.cloneNode(false /* deep */); - this.installButton_.textContent = - str('INSTALL_LINUX_PACKAGE_INSTALL_BUTTON'); - this.installButton_.addEventListener( - 'click', this.onInstallClick_.bind(this)); - this.buttons.insertBefore(this.installButton_, this.okButton_); - this.initialFocusElement_ = this.installButton_; - } + // The OK button normally dismisses the dialog, so add a button we can + // customize. + this.installButton_ = this.okButton_.cloneNode(false /* deep */); + this.installButton_.textContent = + str('INSTALL_LINUX_PACKAGE_INSTALL_BUTTON'); + this.installButton_.addEventListener( + 'click', this.onInstallClick_.bind(this)); + this.buttons.insertBefore(this.installButton_, this.okButton_); + this.initialFocusElement_ = this.installButton_; - InstallLinuxPackageDialog.prototype = { - __proto__: FileManagerDialogBase.prototype, - }; - - /** - * Shows the dialog. - * - * @param {!Entry} entry - */ - InstallLinuxPackageDialog.prototype.showInstallLinuxPackageDialog = function( - entry) { - // We re-use the same object, so reset any visual state that may be changed. - this.installButton_.hidden = false; - this.okButton_.hidden = true; - this.cancelButton_.hidden = false; - - this.entry_ = entry; - - const title = str('INSTALL_LINUX_PACKAGE_TITLE'); - const message = str('INSTALL_LINUX_PACKAGE_DESCRIPTION'); - const show = FileManagerDialogBase.prototype.showOkCancelDialog.call( - this, title, message, null, null); - - if (!show) { - console.error('InstallLinuxPackageDialog can\'t be shown.'); - return; + /** @private {?Entry} */ + this.entry_ = null; } - chrome.fileManagerPrivate.getLinuxPackageInfo( - this.entry_, this.onGetLinuxPackageInfo_.bind(this)); - this.resetDetailsFrame_(str('INSTALL_LINUX_PACKAGE_DETAILS_LOADING')); - }; + /** + * Shows the dialog. + * + * @param {!Entry} entry + */ + showInstallLinuxPackageDialog(entry) { + // We re-use the same object, so reset any visual state that may be + // changed. + this.installButton_.hidden = false; + this.okButton_.hidden = true; + this.cancelButton_.hidden = false; - /** - * Resets the state of the details frame to just contain the 'Details' label, - * then appends |message| if non-empty. - * - * @param {string|null} message The (optional) message to display. - */ - InstallLinuxPackageDialog.prototype.resetDetailsFrame_ = function(message) { - this.details_frame_.innerHTML = ''; - this.details_frame_.appendChild(this.details_label_); - if (message) { - const text = this.document_.createElement('div'); - text.textContent = message; - text.className = 'install-linux-package-detail-value'; - this.details_frame_.appendChild(text); - } - }; + this.entry_ = entry; - /** - * Updates the dialog with the package info. - * - * @param {(!chrome.fileManagerPrivate.LinuxPackageInfo|undefined)} - * linux_package_info The retrieved package info. - */ - InstallLinuxPackageDialog.prototype.onGetLinuxPackageInfo_ = function( - linux_package_info) { - if (chrome.runtime.lastError) { - this.resetDetailsFrame_( - str('INSTALL_LINUX_PACKAGE_DETAILS_NOT_AVAILABLE')); - console.error( - 'Failed to retrieve app info: ' + chrome.runtime.lastError.message); - return; - } + const title = str('INSTALL_LINUX_PACKAGE_TITLE'); + const message = str('INSTALL_LINUX_PACKAGE_DESCRIPTION'); + const show = super.showOkCancelDialog(title, message, null, null); - this.resetDetailsFrame_(null); - - const details = [ - [ - str('INSTALL_LINUX_PACKAGE_DETAILS_APPLICATION_LABEL'), - linux_package_info.name - ], - [ - str('INSTALL_LINUX_PACKAGE_DETAILS_VERSION_LABEL'), - linux_package_info.version - ], - ]; - - // Summary and description are almost always set, but handle the case - // where they're missing gracefully. - let description = linux_package_info.summary; - if (linux_package_info.description) { - if (description) { - description += '\n\n'; + if (!show) { + console.error('InstallLinuxPackageDialog can\'t be shown.'); + return; } - description += linux_package_info.description; - } - if (description) { - details.push([ - str('INSTALL_LINUX_PACKAGE_DETAILS_DESCRIPTION_LABEL'), description - ]); + + chrome.fileManagerPrivate.getLinuxPackageInfo( + this.entry_, this.onGetLinuxPackageInfo_.bind(this)); + this.resetDetailsFrame_(str('INSTALL_LINUX_PACKAGE_DETAILS_LOADING')); } - for (const detail of details) { - const label = this.document_.createElement('div'); - label.textContent = detail[0] + ': '; - label.className = 'install-linux-package-detail-label'; - const text = this.document_.createElement('div'); - text.textContent = detail[1]; - text.className = 'install-linux-package-detail-value'; - this.details_frame_.appendChild(label); - this.details_frame_.appendChild(text); - this.details_frame_.appendChild(this.document_.createElement('br')); - } - }; - - /** - * Starts installing the Linux package. - */ - InstallLinuxPackageDialog.prototype.onInstallClick_ = function() { - // Add the event listener first to avoid potential races. - chrome.fileManagerPrivate.installLinuxPackage( - this.entry_, this.onInstallLinuxPackage_.bind(this)); - - this.installButton_.hidden = true; - this.cancelButton_.hidden = true; - - this.okButton_.hidden = false; - this.okButton_.focus(); - }; - - /** - * The callback for installLinuxPackage(). Progress updates and completion - * for succesfully started installations will be displayed in a notification, - * rather than the file manager. - * @param {!chrome.fileManagerPrivate.InstallLinuxPackageResponse} response - * Whether the install successfully started or not. - * @param {string} failure_reason A textual reason for the 'failed' case. - */ - InstallLinuxPackageDialog.prototype.onInstallLinuxPackage_ = function( - response, failure_reason) { - if (response == 'started') { - this.text_.textContent = - str('INSTALL_LINUX_PACKAGE_INSTALLATION_STARTED'); - return; + /** + * Resets the state of the details frame to just contain the 'Details' + * label, then appends |message| if non-empty. + * + * @param {string|null} message The (optional) message to display. + */ + resetDetailsFrame_(message) { + this.details_frame_.innerHTML = ''; + this.details_frame_.appendChild(this.details_label_); + if (message) { + const text = this.document_.createElement('div'); + text.textContent = message; + text.className = 'install-linux-package-detail-value'; + this.details_frame_.appendChild(text); + } } - // Currently we always display a generic error message. Eventually we'll - // want a different message for the 'install_already_active' case, and to - // surface the provided failure reason if one is provided. - this.title_.textContent = str('INSTALL_LINUX_PACKAGE_ERROR_TITLE'); - this.text_.textContent = str('INSTALL_LINUX_PACKAGE_ERROR_DESCRIPTION'); - console.error('Failed to begin package installation: ' + failure_reason); - }; + /** + * Updates the dialog with the package info. + * + * @param {(!chrome.fileManagerPrivate.LinuxPackageInfo|undefined)} + * linux_package_info The retrieved package info. + */ + onGetLinuxPackageInfo_(linux_package_info) { + if (chrome.runtime.lastError) { + this.resetDetailsFrame_( + str('INSTALL_LINUX_PACKAGE_DETAILS_NOT_AVAILABLE')); + console.error( + 'Failed to retrieve app info: ' + chrome.runtime.lastError.message); + return; + } + + this.resetDetailsFrame_(null); + + const details = [ + [ + str('INSTALL_LINUX_PACKAGE_DETAILS_APPLICATION_LABEL'), + linux_package_info.name + ], + [ + str('INSTALL_LINUX_PACKAGE_DETAILS_VERSION_LABEL'), + linux_package_info.version + ], + ]; + + // Summary and description are almost always set, but handle the case + // where they're missing gracefully. + let description = linux_package_info.summary; + if (linux_package_info.description) { + if (description) { + description += '\n\n'; + } + description += linux_package_info.description; + } + if (description) { + details.push([ + str('INSTALL_LINUX_PACKAGE_DETAILS_DESCRIPTION_LABEL'), description + ]); + } + + for (const detail of details) { + const label = this.document_.createElement('div'); + label.textContent = detail[0] + ': '; + label.className = 'install-linux-package-detail-label'; + const text = this.document_.createElement('div'); + text.textContent = detail[1]; + text.className = 'install-linux-package-detail-value'; + this.details_frame_.appendChild(label); + this.details_frame_.appendChild(text); + this.details_frame_.appendChild(this.document_.createElement('br')); + } + } + + /** + * Starts installing the Linux package. + */ + onInstallClick_() { + // Add the event listener first to avoid potential races. + chrome.fileManagerPrivate.installLinuxPackage( + assert(this.entry_), this.onInstallLinuxPackage_.bind(this)); + + this.installButton_.hidden = true; + this.cancelButton_.hidden = true; + + this.okButton_.hidden = false; + this.okButton_.focus(); + } + + /** + * The callback for installLinuxPackage(). Progress updates and completion + * for successfully started installations will be displayed in a + * notification, rather than the file manager. + * @param {!chrome.fileManagerPrivate.InstallLinuxPackageResponse} response + * Whether the install successfully started or not. + * @param {string} failure_reason A textual reason for the 'failed' case. + */ + onInstallLinuxPackage_(response, failure_reason) { + if (response == 'started') { + this.text_.textContent = + str('INSTALL_LINUX_PACKAGE_INSTALLATION_STARTED'); + return; + } + + // Currently we always display a generic error message. Eventually we'll + // want a different message for the 'install_already_active' case, and to + // surface the provided failure reason if one is provided. + this.title_.textContent = str('INSTALL_LINUX_PACKAGE_ERROR_TITLE'); + this.text_.textContent = str('INSTALL_LINUX_PACKAGE_ERROR_DESCRIPTION'); + console.error('Failed to begin package installation: ' + failure_reason); + } + } return {InstallLinuxPackageDialog: InstallLinuxPackageDialog}; });
diff --git a/ui/file_manager/file_manager/foreground/js/ui/multi_profile_share_dialog.js b/ui/file_manager/file_manager/foreground/js/ui/multi_profile_share_dialog.js index 39230b43..f091e10 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/multi_profile_share_dialog.js +++ b/ui/file_manager/file_manager/foreground/js/ui/multi_profile_share_dialog.js
@@ -5,48 +5,79 @@ /** * Dialog to confirm the share between profiles. * - * @param {HTMLElement} parentNode Node to be parent for this dialog. - * @constructor - * @extends {FileManagerDialogBase} */ -function MultiProfileShareDialog(parentNode) { - FileManagerDialogBase.call(this, parentNode); +class MultiProfileShareDialog extends FileManagerDialogBase { + /** + * @param {HTMLElement} parentNode Node to be parent for this dialog. + */ + constructor(parentNode) { + super(parentNode); - this.mailLabel_ = parentNode.ownerDocument.createElement('label'); - this.mailLabel_.className = 'mail-label'; + this.mailLabel_ = parentNode.ownerDocument.createElement('label'); + this.mailLabel_.className = 'mail-label'; - const canEdit = parentNode.ownerDocument.createElement('option'); - canEdit.textContent = str('DRIVE_SHARE_TYPE_CAN_EDIT'); - canEdit.value = MultiProfileShareDialog.Result.CAN_EDIT; + const canEdit = parentNode.ownerDocument.createElement('option'); + canEdit.textContent = str('DRIVE_SHARE_TYPE_CAN_EDIT'); + canEdit.value = MultiProfileShareDialog.Result.CAN_EDIT; - const canComment = parentNode.ownerDocument.createElement('option'); - canComment.textContent = str('DRIVE_SHARE_TYPE_CAN_COMMENT'); - canComment.value = MultiProfileShareDialog.Result.CAN_COMMET; + const canComment = parentNode.ownerDocument.createElement('option'); + canComment.textContent = str('DRIVE_SHARE_TYPE_CAN_COMMENT'); + canComment.value = MultiProfileShareDialog.Result.CAN_COMMET; - const canView = parentNode.ownerDocument.createElement('option'); - canView.textContent = str('DRIVE_SHARE_TYPE_CAN_VIEW'); - canView.value = MultiProfileShareDialog.Result.CAN_VIEW; + const canView = parentNode.ownerDocument.createElement('option'); + canView.textContent = str('DRIVE_SHARE_TYPE_CAN_VIEW'); + canView.value = MultiProfileShareDialog.Result.CAN_VIEW; - this.shareTypeSelect_ = parentNode.ownerDocument.createElement('select'); - this.shareTypeSelect_.setAttribute('size', 1); - this.shareTypeSelect_.appendChild(canEdit); - this.shareTypeSelect_.appendChild(canComment); - this.shareTypeSelect_.appendChild(canView); + this.shareTypeSelect_ = parentNode.ownerDocument.createElement('select'); + this.shareTypeSelect_.setAttribute('size', 1); + this.shareTypeSelect_.appendChild(canEdit); + this.shareTypeSelect_.appendChild(canComment); + this.shareTypeSelect_.appendChild(canView); - const shareLine = parentNode.ownerDocument.createElement('div'); - shareLine.className = 'share-line'; - shareLine.appendChild(this.mailLabel_); - shareLine.appendChild(this.shareTypeSelect_); + const shareLine = parentNode.ownerDocument.createElement('div'); + shareLine.className = 'share-line'; + shareLine.appendChild(this.mailLabel_); + shareLine.appendChild(this.shareTypeSelect_); - this.frame_.insertBefore(shareLine, this.buttons); - this.frame_.id = 'multi-profile-share-dialog'; + this.frame_.insertBefore(shareLine, this.buttons); + this.frame_.id = 'multi-profile-share-dialog'; - this.currentProfileId_ = new Promise(callback => { - chrome.fileManagerPrivate.getProfiles( - (profiles, currentId, displayedId) => { - callback(currentId); - }); - }); + this.currentProfileId_ = new Promise(callback => { + chrome.fileManagerPrivate.getProfiles( + (profiles, currentId, displayedId) => { + callback(currentId); + }); + }); + } + + /** + * Shows the dialog. + * @param {boolean} plural Whether to use message of plural or not. + * @return {!Promise} Promise fulfilled with the result of dialog. If the + * dialog is already opened, it returns null. + */ + showMultiProfileShareDialog(plural) { + return this.currentProfileId_.then(currentProfileId => { + return new Promise((fulfill, reject) => { + this.shareTypeSelect_.selectedIndex = 0; + this.mailLabel_.textContent = currentProfileId; + const result = super.showOkCancelDialog( + str(plural ? 'MULTI_PROFILE_SHARE_DIALOG_TITLE_PLURAL' : + 'MULTI_PROFILE_SHARE_DIALOG_TITLE'), + str(plural ? 'MULTI_PROFILE_SHARE_DIALOG_MESSAGE_PLURAL' : + 'MULTI_PROFILE_SHARE_DIALOG_MESSAGE'), + () => { + fulfill(this.shareTypeSelect_.value); + }, + () => { + fulfill(MultiProfileShareDialog.Result.CANCEL); + }); + if (!result) { + reject(new Error('Another dialog has already shown.')); + } + }); + }); + } } /** @@ -61,38 +92,3 @@ CANCEL: 'cancel' }; Object.freeze(MultiProfileShareDialog.Result); - -MultiProfileShareDialog.prototype = { - __proto__: FileManagerDialogBase.prototype -}; - -/** - * Shows the dialog. - * @param {boolean} plural Whether to use message of plural or not. - * @return {!Promise} Promise fulfilled with the result of dialog. If the dialog - * is already opened, it returns null. - */ -MultiProfileShareDialog.prototype.showMultiProfileShareDialog = function( - plural) { - return this.currentProfileId_.then(currentProfileId => { - return new Promise((fulfill, reject) => { - this.shareTypeSelect_.selectedIndex = 0; - this.mailLabel_.textContent = currentProfileId; - const result = FileManagerDialogBase.prototype.showOkCancelDialog.call( - this, - str(plural ? 'MULTI_PROFILE_SHARE_DIALOG_TITLE_PLURAL' : - 'MULTI_PROFILE_SHARE_DIALOG_TITLE'), - str(plural ? 'MULTI_PROFILE_SHARE_DIALOG_MESSAGE_PLURAL' : - 'MULTI_PROFILE_SHARE_DIALOG_MESSAGE'), - () => { - fulfill(this.shareTypeSelect_.value); - }, - () => { - fulfill(MultiProfileShareDialog.Result.CANCEL); - }); - if (!result) { - reject(new Error('Another dialog has already shown.')); - } - }); - }); -};
diff --git a/ui/file_manager/file_manager/foreground/js/ui/suggest_apps_dialog.js b/ui/file_manager/file_manager/foreground/js/ui/suggest_apps_dialog.js index 83b415b..b84349aa 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/suggest_apps_dialog.js +++ b/ui/file_manager/file_manager/foreground/js/ui/suggest_apps_dialog.js
@@ -11,59 +11,343 @@ /** * Creates dialog in DOM tree. * - * @param {!ProvidersModel} providersModel Model for providers. - * @param {!HTMLElement} parentNode Node to be parent for this dialog. - * @param {!SuggestAppDialogState} state Static state of suggest app dialog. - * @constructor - * @extends {FileManagerDialogBase} */ -function SuggestAppsDialog(providersModel, parentNode, state) { - FileManagerDialogBase.call(this, parentNode); - +class SuggestAppsDialog extends FileManagerDialogBase { /** - * @private {!ProvidersModel} - * @const + * @param {!ProvidersModel} providersModel Model for providers. + * @param {!HTMLElement} parentNode Node to be parent for this dialog. + * @param {!SuggestAppDialogState} state Static state of suggest app dialog. */ - this.providersModel_ = providersModel; + constructor(providersModel, parentNode, state) { + super(parentNode); - this.frame_.id = 'suggest-app-dialog'; + /** + * @private {!ProvidersModel} + * @const + */ + this.providersModel_ = providersModel; + + this.frame_.id = 'suggest-app-dialog'; + + /** + * The root element for the Chrome Web Store widget container. + * @const {!HTMLElement} + */ + const widgetRoot = this.document_.createElement('div'); + this.frame_.insertBefore(widgetRoot, this.text_.nextSibling); + + /** + * The wrapper around Chrome Web Store widget. + * @const {!CWSWidgetContainer} + * @private + */ + this.widget_ = new CWSWidgetContainer( + this.document_, widgetRoot, this.createWidgetPlatformDelegate_(), + state); + + this.initialFocusElement_ = this.widget_.getInitiallyFocusedElement(); + + /** + * The reported widget result. + * @type {SuggestAppsDialog.Result} + * @private + */ + this.result_ = SuggestAppsDialog.Result.FAILED; + + // Hide default dialog buttons. + this.buttons.hidden = true; + + // Override default dialog styles. + this.title_.classList.add('suggest-apps-dialog-title'); + this.text_.classList.add('suggest-apps-dialog-text'); + + /** @private {?string} */ + this.installedItemId_ = null; + + /** @private {?function(SuggestAppsDialog.Result, ?string)} */ + this.onDialogClosed_ = null; + + /** @private {string} */ + this.dialogText_ = ''; + } /** - * The root element for the Chrome Web Store widget container. - * @const {!HTMLElement} + * Dummy function for SuggestAppsDialog.show() not to be called + * unintentionally. */ - const widgetRoot = this.document_.createElement('div'); - this.frame_.insertBefore(widgetRoot, this.text_.nextSibling); + show() { + console.error('SuggestAppsDialog.show() shouldn\'t be called directly.'); + } /** - * The wrapper around Chrome Web Store widget. - * @const {!CWSWidgetContainer} + * Shows suggest-apps dialog by file extension and mime. + * + * @param {string} extension Extension of the file with a trailing dot. + * @param {?string} mime Mime of the file. + * @param {function(SuggestAppsDialog.Result, ?string)} onDialogClosed Called + * when the dialog is closed, with a result code and an optionally an + * extension id, if an extension was installed. + */ + showByExtensionAndMime(extension, mime, onDialogClosed) { + assert(extension && extension[0] === '.'); + const options = {file_extension: extension.substr(1)}; + if (mime) { + options.mime_type = mime; + } + this.showInternal_( + options, str('SUGGEST_DIALOG_TITLE'), + webStoreUtils.createWebStoreLink(extension, mime), onDialogClosed); + } + + /** + * Shows suggest-apps dialog for FSP API + * @param {function(SuggestAppsDialog.Result, ?string)} onDialogClosed Called + * when the dialog is closed, with a result code and an optionally an + * extension id, if an extension was installed. + */ + showProviders(onDialogClosed) { + this.showInternal_( + {file_system_provider: true}, str('SUGGEST_DIALOG_FOR_PROVIDERS_TITLE'), + null /* webStoreUrl */, onDialogClosed); + } + + /** + * Creates platform delegate for CWSWidgetContainer. + * @return {!CWSWidgetContainerPlatformDelegate} * @private */ - this.widget_ = new CWSWidgetContainer( - this.document_, widgetRoot, this.createWidgetPlatformDelegate_(), state); + createWidgetPlatformDelegate_() { + return { + strings: { + UI_LOCALE: util.getCurrentLocaleOrDefault(), + LINK_TO_WEBSTORE: str('SUGGEST_DIALOG_LINK_TO_WEBSTORE'), + INSTALLATION_FAILED_MESSAGE: str('SUGGEST_DIALOG_INSTALLATION_FAILED'), + LOADING_SPINNER_ALT: str('SUGGEST_DIALOG_LOADING_SPINNER_ALT'), + INSTALLING_SPINNER_ALT: str('SUGGEST_DIALOG_INSTALLING_SPINNER_ALT') + }, - this.initialFocusElement_ = this.widget_.getInitiallyFocusedElement(); + metricsImpl: { + /** + * @param {string} enumName + * @param {number} value + * @param {number} enumSize + */ + recordEnum: function(enumName, value, enumSize) { + metrics.recordEnum('SuggestApps.' + enumName, value, enumSize); + }, + + /** @param {string} actionName */ + recordUserAction: function(actionName) { + metrics.recordUserAction('SuggestApps.' + actionName); + }, + + /** @param {string} intervalName */ + startInterval: function(intervalName) { + metrics.startInterval('SuggestApps.' + intervalName); + }, + + /** @param {string} intervalName */ + recordInterval: function(intervalName) { + metrics.recordInterval('SuggestApps.' + intervalName); + } + }, + + /** + * @param {string} itemId, + * @param {function(?string)} callback Callback argument is set to error + * message (null on success) + */ + installWebstoreItem: function(itemId, callback) { + chrome.webstoreWidgetPrivate.installWebstoreItem( + itemId, false /* show installation prompt */, () => { + callback( + chrome.runtime.lastError ? + chrome.runtime.lastError.message || 'UNKNOWN ERROR' : + null); + }); + }, + + /** + * @param {function(?Array<!string>)} callback Callback + * argument is a list of installed item ids (null on error). + */ + getInstalledItems: callback => { + // Return only installed provided extensions. Returning other + // extensions/apps is redundant, as the suggest app for non-providers is + // executed only when there is no extension/app matching a file task. + // Hence, none of the suggested extensions/apps can be already + // installed. + this.providersModel_.getInstalledProviders() + .then(providers => { + callback(providers.map(provider => { + // Assume that the provider is an extension backed provider. In + // such case the providerId is the same as extensionId. + return provider.providerId; + })); + }) + .catch(error => { + console.error(error.stack || error); + callback(null); + }); + }, + + /** + * @param {function(?string)} callback Callback argument is the requested + * token (null on error). + */ + requestWebstoreAccessToken: function(callback) { + chrome.fileManagerPrivate.requestWebStoreAccessToken(token => { + if (chrome.runtime.lastError) { + console.error(chrome.runtime.lastError.message); + callback(null); + return; + } + callback(assert(token)); + }); + } + }; + } /** - * The reported widget result. - * @type {SuggestAppsDialog.Result} + * Internal method to show a dialog. This should be called only from 'Suggest. + * appDialog.showXxxx()' functions. + * + * @param {!Object<*>} options Map of options for the dialog. + * @param {string} title Title of the dialog. + * @param {?string} webStoreUrl Url for more results. Null if not supported. + * @param {function(SuggestAppsDialog.Result, ?string)} onDialogClosed Called + * when the dialog is closed, with a result code and an optionally an + * extension id, if an extension was installed. * @private */ - this.result_ = SuggestAppsDialog.Result.FAILED; + showInternal_(options, title, webStoreUrl, onDialogClosed) { + this.text_.hidden = true; + this.dialogText_ = ''; - // Hide default dialog buttons. - this.buttons.hidden = true; + if (!this.widget_.isInInitialState()) { + onDialogClosed(SuggestAppsDialog.Result.CANCELLED, null); + return; + } - // Override default dialog styles. - this.title_.classList.add('suggest-apps-dialog-title'); - this.text_.classList.add('suggest-apps-dialog-text'); + let dialogShown = false; + let tokenObtained = false; + + this.widget_.ready() + .then(/** @return {!Promise} */ + () => { + tokenObtained = true; + return this.showDialog_(title); + }) + .then(/** @return {!Promise<CWSWidgetContainer.ResolveReason>} */ + () => { + dialogShown = true; + // This is not set before so it doesn't pollute state if the + // previous dialog hasn't finished hiding. + this.onDialogClosed_ = onDialogClosed; + return this.widget_.start(options, webStoreUrl); + }) + .then(/** @param {CWSWidgetContainer.ResolveReason} reason */ + reason => { + if (reason !== CWSWidgetContainer.ResolveReason.RESET) { + this.hide(); + } + }) + .catch(error => { + console.error('Failed to start CWS widget: ' + error); + + if (!dialogShown) { + // Reset any widget state set in |this.widget_.ready()|. The + // returned value is ignored because it doesn't influence the + // value reported by dialog. + this.widget_.finalizeAndGetResult(); + + const result = tokenObtained ? + // Got access token but the widget dialog was not shown. + // Consider the widget was cancelled. + SuggestAppsDialog.Result.CANCELLED : + // Access token was unavailable. + // This can happen in the Guest mode. crbug.com/694419 + // Callback shows an alert notifying the file was not opened + // because of the unsupported type. + SuggestAppsDialog.Result.FAILED; + onDialogClosed(result, null); + return; + } + + this.result_ = SuggestAppsDialog.Result.FAILED; + this.hide(); + }); + } + + /** + * Internal method for showing the dialog in the file manager window. + * @param {string} title The dialog title. + * @return {!Promise} + */ + showDialog_(title) { + return new Promise((resolve, reject) => { + const success = this.dialogText_ ? + super.showTitleAndTextDialog(title, this.dialogText_) : + super.showTitleOnlyDialog(title); + if (!success) { + reject('SuggestAppsDialog cannot be shown.'); + return; + } + resolve(); + }); + } + + /** + * Called when the connection status is changed. + * @param {VolumeManagerCommon.DriveConnectionType} connectionType Current + * connection type. + */ + onDriveConnectionChanged(connectionType) { + if (connectionType === VolumeManagerCommon.DriveConnectionType.OFFLINE) { + this.widget_.onConnectionLost(); + } + } + + /** + * @param {Function=} opt_originalOnHide Called when the original dialog is + * hidden. + * @override + */ + hide(opt_originalOnHide) { + const widgetResult = this.widget_.finalizeAndGetResult(); + + switch (widgetResult.result) { + case CWSWidgetContainer.Result.INSTALL_SUCCESSFUL: + this.result_ = SuggestAppsDialog.Result.SUCCESS; + break; + case CWSWidgetContainer.Result.WEBSTORE_LINK_OPENED: + case CWSWidgetContainer.Result.USER_CANCEL: + this.result_ = SuggestAppsDialog.Result.CANCELLED; + break; + default: + this.result_ = SuggestAppsDialog.Result.FAILED; + } + + this.installedItemId_ = widgetResult.installedItemId; + + super.hide(this.onHide_.bind(this, opt_originalOnHide)); + } + + /** + * @param {Function=} opt_originalOnHide Original onHide function passed to + * SuggestAppsDialog.hide(). + * @private + */ + onHide_(opt_originalOnHide) { + // Calls the callback after the dialog hides. + if (opt_originalOnHide) { + opt_originalOnHide(); + } + + this.onDialogClosed_(this.result_, this.installedItemId_); + } } -SuggestAppsDialog.prototype = { - __proto__: FileManagerDialogBase.prototype -}; - /** * @enum {string} */ @@ -76,282 +360,3 @@ FAILED: 'SuggestAppsDialog.Result.FAILED' }; Object.freeze(SuggestAppsDialog.Result); - -/** - * Dummy function for SuggestAppsDialog.show() not to be called unintentionally. - */ -SuggestAppsDialog.prototype.show = () => { - console.error('SuggestAppsDialog.show() shouldn\'t be called directly.'); -}; - -/** - * Shows suggest-apps dialog by file extension and mime. - * - * @param {string} extension Extension of the file with a trailing dot. - * @param {?string} mime Mime of the file. - * @param {function(SuggestAppsDialog.Result, ?string)} onDialogClosed Called - * when the dialog is closed, with a result code and an optionally an - * extension id, if an extension was installed. - */ -SuggestAppsDialog.prototype.showByExtensionAndMime = function( - extension, mime, onDialogClosed) { - assert(extension && extension[0] === '.'); - const options = {file_extension: extension.substr(1)}; - if (mime) { - options.mime_type = mime; - } - this.showInternal_( - options, str('SUGGEST_DIALOG_TITLE'), - webStoreUtils.createWebStoreLink(extension, mime), onDialogClosed); -}; - -/** - * Shows suggest-apps dialog for FSP API - * @param {function(SuggestAppsDialog.Result, ?string)} onDialogClosed Called - * when the dialog is closed, with a result code and an optionally an - * extension id, if an extension was installed. - */ -SuggestAppsDialog.prototype.showProviders = function(onDialogClosed) { - this.showInternal_( - {file_system_provider: true}, str('SUGGEST_DIALOG_FOR_PROVIDERS_TITLE'), - null /* webStoreUrl */, onDialogClosed); -}; - -/** - * Creates platform delegate for CWSWidgetContainer. - * @return {!CWSWidgetContainerPlatformDelegate} - * @private - */ -SuggestAppsDialog.prototype.createWidgetPlatformDelegate_ = function() { - return { - strings: { - UI_LOCALE: util.getCurrentLocaleOrDefault(), - LINK_TO_WEBSTORE: str('SUGGEST_DIALOG_LINK_TO_WEBSTORE'), - INSTALLATION_FAILED_MESSAGE: str('SUGGEST_DIALOG_INSTALLATION_FAILED'), - LOADING_SPINNER_ALT: str('SUGGEST_DIALOG_LOADING_SPINNER_ALT'), - INSTALLING_SPINNER_ALT: str('SUGGEST_DIALOG_INSTALLING_SPINNER_ALT') - }, - - metricsImpl: { - /** - * @param {string} enumName - * @param {number} value - * @param {number} enumSize - */ - recordEnum: function(enumName, value, enumSize) { - metrics.recordEnum('SuggestApps.' + enumName, value, enumSize); - }, - - /** @param {string} actionName */ - recordUserAction: function(actionName) { - metrics.recordUserAction('SuggestApps.' + actionName); - }, - - /** @param {string} intervalName */ - startInterval: function(intervalName) { - metrics.startInterval('SuggestApps.' + intervalName); - }, - - /** @param {string} intervalName */ - recordInterval: function(intervalName) { - metrics.recordInterval('SuggestApps.' + intervalName); - } - }, - - /** - * @param {string} itemId, - * @param {function(?string)} callback Callback argument is set to error - * message (null on success) - */ - installWebstoreItem: function(itemId, callback) { - chrome.webstoreWidgetPrivate.installWebstoreItem( - itemId, false /* show installation prompt */, () => { - callback( - chrome.runtime.lastError ? - chrome.runtime.lastError.message || 'UNKNOWN ERROR' : - null); - }); - }, - - /** - * @param {function(?Array<!string>)} callback Callback - * argument is a list of installed item ids (null on error). - */ - getInstalledItems: callback => { - // Return only installed provided extensions. Returning other - // extensions/apps is redundant, as the suggest app for non-providers is - // executed only when there is no extension/app matching a file task. - // Hence, none of the suggested extensions/apps can be already installed. - this.providersModel_.getInstalledProviders() - .then(providers => { - callback(providers.map(provider => { - // Assume that the provider is an extension backed provider. In - // such case the providerId is the same as extensionId. - return provider.providerId; - })); - }) - .catch(error => { - console.error(error.stack || error); - callback(null); - }); - }, - - /** - * @param {function(?string)} callback Callback argument is the requested - * token (null on error). - */ - requestWebstoreAccessToken: function(callback) { - chrome.fileManagerPrivate.requestWebStoreAccessToken(token => { - if (chrome.runtime.lastError) { - console.error(chrome.runtime.lastError.message); - callback(null); - return; - } - callback(assert(token)); - }); - } - }; -}; - -/** - * Internal method to show a dialog. This should be called only from 'Suggest. - * appDialog.showXxxx()' functions. - * - * @param {!Object<*>} options Map of options for the dialog. - * @param {string} title Title of the dialog. - * @param {?string} webStoreUrl Url for more results. Null if not supported. - * @param {function(SuggestAppsDialog.Result, ?string)} onDialogClosed Called - * when the dialog is closed, with a result code and an optionally an - * extension id, if an extension was installed. - * @private - */ -SuggestAppsDialog.prototype.showInternal_ = function( - options, title, webStoreUrl, onDialogClosed) { - this.text_.hidden = true; - this.dialogText_ = ''; - - if (!this.widget_.isInInitialState()) { - onDialogClosed(SuggestAppsDialog.Result.CANCELLED, null); - return; - } - - let dialogShown = false; - let tokenObtained = false; - - this.widget_.ready() - .then(/** @return {!Promise} */ - () => { - tokenObtained = true; - return this.showDialog_(title); - }) - .then(/** @return {!Promise<CWSWidgetContainer.ResolveReason>} */ - () => { - dialogShown = true; - // This is not set before so it doesn't pollute state if the - // previous dialog hasn't finished hiding. - this.onDialogClosed_ = onDialogClosed; - return this.widget_.start(options, webStoreUrl); - }) - .then(/** @param {CWSWidgetContainer.ResolveReason} reason */ - reason => { - if (reason !== CWSWidgetContainer.ResolveReason.RESET) { - this.hide(); - } - }) - .catch(error => { - console.error('Failed to start CWS widget: ' + error); - - if (!dialogShown) { - // Reset any widget state set in |this.widget_.ready()|. The - // returned value is ignored because it doesn't influence the - // value reported by dialog. - this.widget_.finalizeAndGetResult(); - - const result = tokenObtained ? - // Got access token but the widget dialog was not shown. - // Consider the widget was cancelled. - SuggestAppsDialog.Result.CANCELLED : - // Access token was unavailable. - // This can happen in the Guest mode. crbug.com/694419 - // Callback shows an alert notifying the file was not opened - // because of the unsupported type. - SuggestAppsDialog.Result.FAILED; - onDialogClosed(result, null); - return; - } - - this.result_ = SuggestAppsDialog.Result.FAILED; - this.hide(); - }); -}; - -/** - * Internal method for showing the dialog in the file manager window. - * @param {string} title The dialog title. - * @return {!Promise} - */ -SuggestAppsDialog.prototype.showDialog_ = function(title) { - return new Promise((resolve, reject) => { - const success = this.dialogText_ ? - FileManagerDialogBase.prototype.showTitleAndTextDialog.call( - this, title, this.dialogText_) : - FileManagerDialogBase.prototype.showTitleOnlyDialog.call(this, title); - if (!success) { - reject('SuggestAppsDialog cannot be shown.'); - return; - } - resolve(); - }); -}; - -/** - * Called when the connection status is changed. - * @param {VolumeManagerCommon.DriveConnectionType} connectionType Current - * connection type. - */ -SuggestAppsDialog.prototype.onDriveConnectionChanged = function( - connectionType) { - if (connectionType === VolumeManagerCommon.DriveConnectionType.OFFLINE) { - this.widget_.onConnectionLost(); - } -}; - -/** - * @param {Function=} opt_originalOnHide Called when the original dialog is - * hidden. - * @override - */ -SuggestAppsDialog.prototype.hide = function(opt_originalOnHide) { - const widgetResult = this.widget_.finalizeAndGetResult(); - - switch (widgetResult.result) { - case CWSWidgetContainer.Result.INSTALL_SUCCESSFUL: - this.result_ = SuggestAppsDialog.Result.SUCCESS; - break; - case CWSWidgetContainer.Result.WEBSTORE_LINK_OPENED: - case CWSWidgetContainer.Result.USER_CANCEL: - this.result_ = SuggestAppsDialog.Result.CANCELLED; - break; - default: - this.result_ = SuggestAppsDialog.Result.FAILED; - } - - this.installedItemId_ = widgetResult.installedItemId; - - FileManagerDialogBase.prototype.hide.call( - this, this.onHide_.bind(this, opt_originalOnHide)); -}; - -/** - * @param {Function=} opt_originalOnHide Original onHide function passed to - * SuggestAppsDialog.hide(). - * @private - */ -SuggestAppsDialog.prototype.onHide_ = function(opt_originalOnHide) { - // Calls the callback after the dialog hides. - if (opt_originalOnHide) { - opt_originalOnHide(); - } - - this.onDialogClosed_(this.result_, this.installedItemId_); -};
diff --git a/ui/ozone/platform/drm/host/host_cursor_proxy.cc b/ui/ozone/platform/drm/host/host_cursor_proxy.cc index 766980d..d2950b9 100644 --- a/ui/ozone/platform/drm/host/host_cursor_proxy.cc +++ b/ui/ozone/platform/drm/host/host_cursor_proxy.cc
@@ -7,7 +7,6 @@ #include <utility> #include "services/service_manager/public/cpp/connector.h" -#include "services/ws/public/mojom/constants.mojom.h" #include "ui/ozone/public/gpu_platform_support_host.h" namespace ui {
diff --git a/ui/ozone/platform/drm/host/host_drm_device.cc b/ui/ozone/platform/drm/host/host_drm_device.cc index 4ff514f..e4bcc07 100644 --- a/ui/ozone/platform/drm/host/host_drm_device.cc +++ b/ui/ozone/platform/drm/host/host_drm_device.cc
@@ -13,7 +13,6 @@ #include "base/task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "services/service_manager/public/cpp/connector.h" -#include "services/ws/public/mojom/constants.mojom.h" #include "ui/display/types/display_snapshot.h" #include "ui/ozone/platform/drm/common/drm_util.h" #include "ui/ozone/platform/drm/host/drm_device_connector.h"
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc index 1347bbf..d2863a2 100644 --- a/ui/views/controls/textfield/textfield.cc +++ b/ui/views/controls/textfield/textfield.cc
@@ -1758,8 +1758,12 @@ bool Textfield::SetCompositionFromExistingText( const gfx::Range& range, const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) { - NOTIMPLEMENTED_LOG_ONCE(); - return false; + // TODO(https://crbug.com/952355): Support custom text spans. + DCHECK(!model_->HasCompositionText()); + model_->SetCompositionFromExistingText(range); + SchedulePaint(); + OnAfterUserAction(); + return true; } #endif
diff --git a/ui/views/controls/textfield/textfield_model.cc b/ui/views/controls/textfield/textfield_model.cc index 4c3328e4..f65c66fa 100644 --- a/ui/views/controls/textfield/textfield_model.cc +++ b/ui/views/controls/textfield/textfield_model.cc
@@ -669,6 +669,12 @@ } } +void TextfieldModel::SetCompositionFromExistingText(const gfx::Range& range) { + DCHECK(!HasCompositionText()); + composition_range_ = range; + render_text_->SetCompositionRange(range); +} + void TextfieldModel::ConfirmCompositionText() { DCHECK(HasCompositionText()); base::string16 composition = text().substr(
diff --git a/ui/views/controls/textfield/textfield_model.h b/ui/views/controls/textfield/textfield_model.h index 19d434d5..c2391a35 100644 --- a/ui/views/controls/textfield/textfield_model.h +++ b/ui/views/controls/textfield/textfield_model.h
@@ -219,6 +219,10 @@ // composition text. void SetCompositionText(const ui::CompositionText& composition); + // Puts the text in the specified range into composition mode. + // This method should not be called with composition text or an invalid range. + void SetCompositionFromExistingText(const gfx::Range& range); + // Converts current composition text into final content. void ConfirmCompositionText();
diff --git a/ui/views/controls/textfield/textfield_model_unittest.cc b/ui/views/controls/textfield/textfield_model_unittest.cc index 99a863739..27a7566 100644 --- a/ui/views/controls/textfield/textfield_model_unittest.cc +++ b/ui/views/controls/textfield/textfield_model_unittest.cc
@@ -1950,4 +1950,17 @@ EXPECT_STR_EQ("aad", model.text()); } +TEST_F(TextfieldModelTest, SetCompositionFromExistingText) { + TextfieldModel model(nullptr); + model.SetText(base::ASCIIToUTF16("abcde")); + + model.SetCompositionFromExistingText(gfx::Range(1, 3)); + EXPECT_TRUE(model.HasCompositionText()); + + ui::CompositionText composition; + composition.text = base::ASCIIToUTF16("123"); + model.SetCompositionText(composition); + EXPECT_STR_EQ("a123de", model.text()); +} + } // namespace views
diff --git a/ui/webui/resources/cr_components/chromeos/BUILD.gn b/ui/webui/resources/cr_components/chromeos/BUILD.gn index 2ec0ddce..895487a 100644 --- a/ui/webui/resources/cr_components/chromeos/BUILD.gn +++ b/ui/webui/resources/cr_components/chromeos/BUILD.gn
@@ -13,7 +13,6 @@ "multidevice_setup:closure_compile", "network:closure_compile", "quick_unlock:closure_compile", - "smb_shares:closure_compile", ] }
diff --git a/ui/webui/resources/js/cr/ui/dialogs.js b/ui/webui/resources/js/cr/ui/dialogs.js index c404399..59844c2b 100644 --- a/ui/webui/resources/js/cr/ui/dialogs.js +++ b/ui/webui/resources/js/cr/ui/dialogs.js
@@ -44,6 +44,9 @@ /** @protected {?Element} */ this.cancelButton_ = null; + /** @protected {?Element} */ + this.buttons = null; + this.initDom_(); }