diff options
Diffstat (limited to 'chromium/components/arc/intent_helper')
11 files changed, 291 insertions, 14 deletions
diff --git a/chromium/components/arc/intent_helper/DEPS b/chromium/components/arc/intent_helper/DEPS index 8f0dc0b632f..7f66c60dc3b 100644 --- a/chromium/components/arc/intent_helper/DEPS +++ b/chromium/components/arc/intent_helper/DEPS @@ -8,6 +8,8 @@ include_rules = [ "+components/services/app_service/public/cpp", "+components/url_formatter", "+services/service_manager/public/cpp/connector.h", + "+ui/aura", "+ui/base", "+ui/gfx", + "+ui/views", ] diff --git a/chromium/components/arc/intent_helper/activity_icon_loader.cc b/chromium/components/arc/intent_helper/activity_icon_loader.cc index 5bcebf5a201..bbc02cc8245 100644 --- a/chromium/components/arc/intent_helper/activity_icon_loader.cc +++ b/chromium/components/arc/intent_helper/activity_icon_loader.cc @@ -13,6 +13,7 @@ #include "base/bind.h" #include "base/memory/ref_counted.h" #include "base/task/post_task.h" +#include "base/task/thread_pool.h" #include "components/arc/arc_service_manager.h" #include "components/arc/arc_util.h" #include "components/arc/session/arc_bridge_service.h" @@ -252,7 +253,7 @@ void ActivityIconLoader::OnIconsReady( OnIconsReadyCallback cb, std::vector<mojom::ActivityIconPtr> icons) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - base::PostTaskAndReplyWithResult( + base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, base::BindOnce(&ResizeAndEncodeIcons, std::move(icons), scale_factor_), base::BindOnce(&ActivityIconLoader::OnIconsResized, diff --git a/chromium/components/arc/intent_helper/arc_intent_helper_bridge.cc b/chromium/components/arc/intent_helper/arc_intent_helper_bridge.cc index 8878c8f8d6b..ba948dc3077 100644 --- a/chromium/components/arc/intent_helper/arc_intent_helper_bridge.cc +++ b/chromium/components/arc/intent_helper/arc_intent_helper_bridge.cc @@ -144,7 +144,6 @@ void ArcIntentHelperBridge::OnOpenDownloads() { // downloads by default, which is what we want. However if it is open it will // simply be brought to the forgeground without forcibly being navigated to // downloads, which is probably not ideal. - // TODO(mash): Support this functionality without ash::Shell access in Chrome. ash::NewWindowDelegate::GetInstance()->OpenFileManager(); } diff --git a/chromium/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc b/chromium/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc index c48c1ff04bf..d1b8a7aa6e1 100644 --- a/chromium/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc +++ b/chromium/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc @@ -24,9 +24,11 @@ IntentFilter GetIntentFilter(const std::string& host, const std::string& pkg_name) { std::vector<IntentFilter::AuthorityEntry> authorities; authorities.emplace_back(host, /*port=*/-1); - return IntentFilter(pkg_name, std::move(authorities), + return IntentFilter(pkg_name, /*actions=*/std::vector<std::string>(), + std::move(authorities), std::vector<IntentFilter::PatternMatcher>(), - std::vector<std::string>()); + /*schemes=*/std::vector<std::string>(), + /*mime_types=*/std::vector<std::string>()); } } // namespace diff --git a/chromium/components/arc/intent_helper/custom_tab.cc b/chromium/components/arc/intent_helper/custom_tab.cc new file mode 100644 index 00000000000..5af4709668a --- /dev/null +++ b/chromium/components/arc/intent_helper/custom_tab.cc @@ -0,0 +1,160 @@ +// 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/arc/intent_helper/custom_tab.h" + +#include <memory> +#include <string> +#include <utility> + +#include "base/threading/sequenced_task_runner_handle.h" +#include "components/exo/surface.h" +#include "ui/aura/window.h" +#include "ui/aura/window_targeter.h" +#include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_delegate.h" + +namespace arc { + +namespace { + +// Enumerates surfaces under the window. +void EnumerateSurfaces(aura::Window* window, std::vector<exo::Surface*>* out) { + auto* surface = exo::Surface::AsSurface(window); + if (surface) + out->push_back(surface); + for (aura::Window* child : window->children()) + EnumerateSurfaces(child, out); +} + +} // namespace + +CustomTab::CustomTab(aura::Window* arc_app_window, + int32_t surface_id, + int32_t top_margin) + : arc_app_window_(arc_app_window), + surface_id_(surface_id), + top_margin_(top_margin) { + other_windows_observer_.Add(arc_app_window_); + + host_->set_owned_by_client(); + auto* const widget = views::Widget::GetWidgetForNativeWindow(arc_app_window_); + DCHECK(widget); + widget->GetContentsView()->AddChildView(host_.get()); +} + +CustomTab::~CustomTab() = default; + +void CustomTab::Attach(gfx::NativeView view) { + DCHECK(view); + DCHECK(!GetHostView()); + host_->Attach(view); + aura::Window* const container = host_->GetNativeViewContainer(); + container->SetEventTargeter(std::make_unique<aura::WindowTargeter>()); + other_windows_observer_.Add(container); + EnsureWindowOrders(); + UpdateSurfaceIfNecessary(); +} + +gfx::NativeView CustomTab::GetHostView() { + return host_->native_view(); +} + +void CustomTab::OnWindowHierarchyChanged(const HierarchyChangeParams& params) { + if ((params.receiver == arc_app_window_) && + exo::Surface::AsSurface(params.target) && params.new_parent) + UpdateSurfaceIfNecessary(); +} + +void CustomTab::OnWindowBoundsChanged(aura::Window* window, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds, + ui::PropertyChangeReason reason) { + if (surface_window_observer_.IsObserving(window) && + old_bounds.size() != new_bounds.size()) + OnSurfaceBoundsMaybeChanged(window); +} + +void CustomTab::OnWindowPropertyChanged(aura::Window* window, + const void* key, + intptr_t old) { + if (surfaces_observer_.IsObserving(window) && key == exo::kClientSurfaceIdKey) + UpdateSurfaceIfNecessary(); +} + +void CustomTab::OnWindowStackingChanged(aura::Window* window) { + if (window == host_->GetNativeViewContainer() && + !weak_ptr_factory_.HasWeakPtrs()) { + // Reordering should happen asynchronously -- some entity (like + // views::WindowReorderer) changes the window orders, and then ensures layer + // orders later. Changing order here synchronously leads to inconsistent + // window/layer ordering and causes weird graphical effects. + // TODO(hashimoto): fix the views ordering and remove this handling. + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&CustomTab::EnsureWindowOrders, + weak_ptr_factory_.GetWeakPtr())); + } +} + +void CustomTab::OnWindowDestroying(aura::Window* window) { + if (surfaces_observer_.IsObserving(window)) + surfaces_observer_.Remove(window); + if (surface_window_observer_.IsObserving(window)) + surface_window_observer_.Remove(window); + if (other_windows_observer_.IsObserving(window)) + other_windows_observer_.Remove(window); +} + +void CustomTab::OnSurfaceBoundsMaybeChanged(aura::Window* surface_window) { + DCHECK(surface_window); + gfx::Point origin(0, top_margin_); + gfx::Point bottom_right(surface_window->bounds().width(), + surface_window->bounds().height()); + ConvertPointFromWindow(surface_window, &origin); + ConvertPointFromWindow(surface_window, &bottom_right); + host_->SetBounds(origin.x(), origin.y(), bottom_right.x() - origin.x(), + bottom_right.y() - origin.y()); +} + +void CustomTab::EnsureWindowOrders() { + aura::Window* const container = host_->GetNativeViewContainer(); + if (container) + container->parent()->StackChildAtTop(container); +} + +void CustomTab::ConvertPointFromWindow(aura::Window* window, + gfx::Point* point) { + views::Widget* const widget = host_->GetWidget(); + aura::Window::ConvertPointToTarget(window, widget->GetNativeWindow(), point); + views::View::ConvertPointFromWidget(widget->GetContentsView(), point); +} + +void CustomTab::UpdateSurfaceIfNecessary() { + std::vector<exo::Surface*> surfaces; + EnumerateSurfaces(arc_app_window_, &surfaces); + + // Try to find the surface. + const auto it = std::find_if(surfaces.cbegin(), surfaces.cend(), + [id = surface_id_](const auto* surface) { + return surface->GetClientSurfaceId() == id; + }); + if (it == surfaces.cend()) { + for (auto* surface : surfaces) { + if (!surface->GetClientSurfaceId() && + !surfaces_observer_.IsObserving(surface->window())) + surfaces_observer_.Add(surface->window()); + } + } else { + surfaces_observer_.RemoveAll(); + + auto* const window = (*it)->window(); + if (!surface_window_observer_.IsObserving(window)) { + surface_window_observer_.RemoveAll(); + surface_window_observer_.Add(window); + OnSurfaceBoundsMaybeChanged(window); + } + } +} + +} // namespace arc diff --git a/chromium/components/arc/intent_helper/custom_tab.h b/chromium/components/arc/intent_helper/custom_tab.h new file mode 100644 index 00000000000..01815f2c56c --- /dev/null +++ b/chromium/components/arc/intent_helper/custom_tab.h @@ -0,0 +1,76 @@ +// 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_ARC_INTENT_HELPER_CUSTOM_TAB_H_ +#define COMPONENTS_ARC_INTENT_HELPER_CUSTOM_TAB_H_ + +#include <memory> + +#include "base/macros.h" +#include "base/scoped_observer.h" +#include "components/arc/arc_export.h" +#include "ui/aura/window.h" +#include "ui/aura/window_observer.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/views/controls/native/native_view_host.h" + +namespace arc { + +// CustomTab is responsible to embed an ARC++ custom tab. +class ARC_EXPORT CustomTab : public aura::WindowObserver { + public: + CustomTab(aura::Window* arc_app_window, + int32_t surface_id, + int32_t top_margin); + CustomTab(const CustomTab&) = delete; + CustomTab& operator=(const CustomTab&) = delete; + ~CustomTab() override; + + void Attach(gfx::NativeView view); + + // Returns the view against which a view or dialog is positioned and parented + // in an CustomTab. + gfx::NativeView GetHostView(); + + // aura::WindowObserver: + void OnWindowHierarchyChanged(const HierarchyChangeParams& params) override; + void OnWindowBoundsChanged(aura::Window* window, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds, + ui::PropertyChangeReason reason) override; + void OnWindowPropertyChanged(aura::Window* window, + const void* key, + intptr_t old) override; + void OnWindowStackingChanged(aura::Window* window) override; + void OnWindowDestroying(aura::Window* window) override; + + private: + // Updates |host_|'s bounds to deal with changes in the bounds of the + // associated |surface_window|. + void OnSurfaceBoundsMaybeChanged(aura::Window* surface_window); + + // Ensures the window/layer orders for the NativeViewHost. + void EnsureWindowOrders(); + + // Converts the point from the given window to this view. + void ConvertPointFromWindow(aura::Window* window, gfx::Point* point); + + // Looks for the surface with |surface_id_|, and handles resultant changes. + void UpdateSurfaceIfNecessary(); + + std::unique_ptr<views::NativeViewHost> host_ = + std::make_unique<views::NativeViewHost>(); + aura::Window* const arc_app_window_; + const int32_t surface_id_, top_margin_; + ScopedObserver<aura::Window, aura::WindowObserver> surfaces_observer_{this}; + ScopedObserver<aura::Window, aura::WindowObserver> surface_window_observer_{ + this}; + ScopedObserver<aura::Window, aura::WindowObserver> other_windows_observer_{ + this}; + base::WeakPtrFactory<CustomTab> weak_ptr_factory_{this}; +}; + +} // namespace arc + +#endif // COMPONENTS_ARC_INTENT_HELPER_CUSTOM_TAB_H_ diff --git a/chromium/components/arc/intent_helper/intent_filter.cc b/chromium/components/arc/intent_helper/intent_filter.cc index 51d713dbba1..2cb365a24ec 100644 --- a/chromium/components/arc/intent_helper/intent_filter.cc +++ b/chromium/components/arc/intent_helper/intent_filter.cc @@ -4,10 +4,12 @@ #include "components/arc/intent_helper/intent_filter.h" +#include <algorithm> #include <utility> #include "base/compiler_specific.h" #include "base/strings/string_util.h" +#include "components/arc/intent_helper/intent_constants.h" #include "components/arc/mojom/intent_helper.mojom.h" #include "components/services/app_service/public/cpp/intent_util.h" #include "url/gurl.h" @@ -19,12 +21,16 @@ IntentFilter::IntentFilter(IntentFilter&& other) = default; IntentFilter::IntentFilter( const std::string& package_name, + std::vector<std::string> actions, std::vector<IntentFilter::AuthorityEntry> authorities, std::vector<IntentFilter::PatternMatcher> paths, - std::vector<std::string> schemes) + std::vector<std::string> schemes, + std::vector<std::string> mime_types) : package_name_(package_name), + actions_(std::move(actions)), authorities_(std::move(authorities)), - schemes_(std::move(schemes)) { + schemes_(std::move(schemes)), + mime_types_(std::move(mime_types)) { // In order to register a path we need to have at least one authority. if (!authorities_.empty()) paths_ = std::move(paths); @@ -45,6 +51,15 @@ bool IntentFilter::Match(const GURL& url) const { return false; } + // Don't return match for filters for sharing. + if (std::any_of(actions_.begin(), actions_.end(), + [](const std::string action) { + return action == kIntentActionSend || + action == kIntentActionSendMultiple; + })) { + return false; + } + // Match the authority and the path. If there are no authorities for this // filter, we can treat this as a match, since we already know this filter // has a http(s) scheme and it doesn't corresponds to a MIME type. diff --git a/chromium/components/arc/intent_helper/intent_filter.h b/chromium/components/arc/intent_helper/intent_filter.h index db457d03827..de205499e0c 100644 --- a/chromium/components/arc/intent_helper/intent_filter.h +++ b/chromium/components/arc/intent_helper/intent_filter.h @@ -70,9 +70,11 @@ class IntentFilter { IntentFilter(); IntentFilter(IntentFilter&& other); IntentFilter(const std::string& package_name, + std::vector<std::string> actions, std::vector<AuthorityEntry> authorities, std::vector<PatternMatcher> paths, - std::vector<std::string> schemes); + std::vector<std::string> schemes, + std::vector<std::string> mime_types); ~IntentFilter(); IntentFilter& operator=(IntentFilter&& other); @@ -80,20 +82,24 @@ class IntentFilter { bool Match(const GURL& url) const; const std::string& package_name() const { return package_name_; } + const std::vector<std::string>& actions() const { return actions_; } const std::vector<AuthorityEntry>& authorities() const { return authorities_; } const std::vector<PatternMatcher>& paths() const { return paths_; } const std::vector<std::string>& schemes() const { return schemes_; } + const std::vector<std::string>& mime_types() const { return mime_types_; } private: bool MatchDataAuthority(const GURL& url) const; bool HasDataPath(const GURL& url) const; std::string package_name_; + std::vector<std::string> actions_; std::vector<AuthorityEntry> authorities_; std::vector<PatternMatcher> paths_; std::vector<std::string> schemes_; + std::vector<std::string> mime_types_; DISALLOW_COPY_AND_ASSIGN(IntentFilter); }; diff --git a/chromium/components/arc/intent_helper/intent_filter_mojom_traits.cc b/chromium/components/arc/intent_helper/intent_filter_mojom_traits.cc index 16b2b9f0b33..87725074586 100644 --- a/chromium/components/arc/intent_helper/intent_filter_mojom_traits.cc +++ b/chromium/components/arc/intent_helper/intent_filter_mojom_traits.cc @@ -31,8 +31,17 @@ bool StructTraits<arc::mojom::IntentFilterDataView, arc::IntentFilter>::Read( if (!data.ReadDataSchemes(&schemes)) return false; - *out = arc::IntentFilter(package_name, std::move(authorities), - std::move(paths), std::move(schemes)); + std::vector<std::string> actions; + if (!data.ReadActions(&actions)) + return false; + + std::vector<std::string> mime_types; + if (!data.ReadMimeTypes(&mime_types)) + return false; + + *out = arc::IntentFilter(package_name, std::move(actions), + std::move(authorities), std::move(paths), + std::move(schemes), std::move(mime_types)); return true; } diff --git a/chromium/components/arc/intent_helper/intent_filter_mojom_traits.h b/chromium/components/arc/intent_helper/intent_filter_mojom_traits.h index 636efd1d9f1..772f9299db9 100644 --- a/chromium/components/arc/intent_helper/intent_filter_mojom_traits.h +++ b/chromium/components/arc/intent_helper/intent_filter_mojom_traits.h @@ -16,9 +16,8 @@ namespace mojo { template <> struct StructTraits<arc::mojom::IntentFilterDataView, arc::IntentFilter> { - static const base::span<std::string> actions(const arc::IntentFilter& r) { - // Returns an empty array. - return base::span<std::string>(); + static const std::vector<std::string>& actions(const arc::IntentFilter& r) { + return r.actions(); } static const base::span<std::string> categories(const arc::IntentFilter& r) { // Returns an empty array. @@ -46,6 +45,11 @@ struct StructTraits<arc::mojom::IntentFilterDataView, arc::IntentFilter> { return r.package_name(); } + static const std::vector<std::string>& mime_types( + const arc::IntentFilter& r) { + return r.mime_types(); + } + static bool Read(arc::mojom::IntentFilterDataView data, arc::IntentFilter* out); }; diff --git a/chromium/components/arc/intent_helper/intent_filter_unittest.cc b/chromium/components/arc/intent_helper/intent_filter_unittest.cc index a2158cd26f8..4d65eeee9c3 100644 --- a/chromium/components/arc/intent_helper/intent_filter_unittest.cc +++ b/chromium/components/arc/intent_helper/intent_filter_unittest.cc @@ -40,8 +40,11 @@ class IntentFilterBuilder { } operator IntentFilter() { - return IntentFilter(kPackageName, std::move(authorities_), - std::move(paths_), std::vector<std::string>()); + return IntentFilter(kPackageName, + /*actions=*/std::vector<std::string>(), + std::move(authorities_), std::move(paths_), + /*schemes=*/std::vector<std::string>(), + /*mime_types=*/std::vector<std::string>()); } private: |