[M120 Migration]Fix for crash during chrome exit
[platform/framework/web/chromium-efl.git] / chrome / browser / platform_util_mac.mm
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/platform_util.h"
6
7 #import <Cocoa/Cocoa.h>
8
9 #include "base/apple/foundation_util.h"
10 #include "base/apple/osstatus_logging.h"
11 #include "base/command_line.h"
12 #include "base/files/file_path.h"
13 #include "base/files/file_util.h"
14 #include "base/functional/bind.h"
15 #include "base/logging.h"
16 #include "base/strings/sys_string_conversions.h"
17 #include "chrome/browser/platform_util_internal.h"
18 #include "content/public/browser/browser_task_traits.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/common/content_switches.h"
21 #include "net/base/mac/url_conversions.h"
22 #include "ui/views/widget/widget.h"
23 #include "url/gurl.h"
24
25 namespace platform_util {
26
27 // Returns true if revealing file paths in the Finder should be skipped
28 // because it's not needed while running a test.
29 bool WorkspacePathRevealDisabledForTest() {
30   // Note: the kTestType switch is only added on browser tests, but not unit
31   // tests. Unit tests need to add the switch manually:
32   //
33   //   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
34   //   command_line->AppendSwitch(switches::kTestType);
35   //
36   return base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType);
37 }
38
39 void ShowItemInFolder(Profile* profile, const base::FilePath& full_path) {
40   DCHECK([NSThread isMainThread]);
41   NSURL* url = base::apple::FilePathToNSURL(full_path);
42
43   // The Finder creates a new window on each `full_path` reveal. Skip
44   // revealing the path during testing to avoid an avalanche of new
45   // Finder windows.
46   if (WorkspacePathRevealDisabledForTest()) {
47     return;
48   }
49
50   [[NSWorkspace sharedWorkspace] activateFileViewerSelectingURLs:@[ url ]];
51 }
52
53 void OpenFileOnMainThread(const base::FilePath& full_path) {
54   DCHECK([NSThread isMainThread]);
55   NSURL* url = base::apple::FilePathToNSURL(full_path);
56   if (!url)
57     return;
58
59   [[NSWorkspace sharedWorkspace]
60                 openURL:url
61           configuration:[NSWorkspaceOpenConfiguration configuration]
62       completionHandler:nil];
63 }
64
65 namespace internal {
66
67 void PlatformOpenVerifiedItem(const base::FilePath& path, OpenItemType type) {
68   switch (type) {
69     case OPEN_FILE:
70       content::GetUIThreadTaskRunner({})->PostTask(
71           FROM_HERE, base::BindOnce(&OpenFileOnMainThread, path));
72       return;
73     case OPEN_FOLDER:
74       NSURL* url = base::apple::FilePathToNSURL(path);
75       if (!url)
76         return;
77
78       // Note that there exists a TOCTOU race between the time that |path| was
79       // verified as being a directory and when NSWorkspace invokes Finder (or
80       // alternative) to open |path_string|.
81       [[NSWorkspace sharedWorkspace] openURL:url];
82       return;
83   }
84 }
85
86 }  // namespace internal
87
88 void OpenExternal(const GURL& url) {
89   DCHECK([NSThread isMainThread]);
90   NSURL* ns_url = net::NSURLWithGURL(url);
91   if (!ns_url || ![[NSWorkspace sharedWorkspace] openURL:ns_url])
92     LOG(WARNING) << "NSWorkspace failed to open URL " << url;
93 }
94
95 gfx::NativeWindow GetTopLevel(gfx::NativeView view) {
96   return gfx::NativeWindow([view.GetNativeNSView() window]);
97 }
98
99 gfx::NativeView GetViewForWindow(gfx::NativeWindow native_window) {
100   NSWindow* window = native_window.GetNativeNSWindow();
101   DCHECK(window);
102   DCHECK([window contentView]);
103   return gfx::NativeView([window contentView]);
104 }
105
106 gfx::NativeView GetParent(gfx::NativeView view) {
107   return gfx::NativeView(nil);
108 }
109
110 bool IsWindowActive(gfx::NativeWindow native_window) {
111   // If |window| is a doppelganger NSWindow being used to track an NSWindow that
112   // is being hosted in another process, then use the views::Widget interface to
113   // interact with it.
114   views::Widget* widget =
115       views::Widget::GetWidgetForNativeWindow(native_window);
116   if (widget)
117     return widget->IsActive();
118
119   NSWindow* window = native_window.GetNativeNSWindow();
120   return [window isKeyWindow] || [window isMainWindow];
121 }
122
123 void ActivateWindow(gfx::NativeWindow native_window) {
124   views::Widget* widget =
125       views::Widget::GetWidgetForNativeWindow(native_window);
126   if (widget)
127     return widget->Activate();
128
129   NSWindow* window = native_window.GetNativeNSWindow();
130   [window makeKeyAndOrderFront:nil];
131 }
132
133 bool IsVisible(gfx::NativeView native_view) {
134   views::Widget* widget = views::Widget::GetWidgetForNativeView(native_view);
135   if (widget)
136     return widget->IsVisible();
137
138   // A reasonable approximation of how you'd expect this to behave.
139   NSView* view = native_view.GetNativeNSView();
140   return (view &&
141           ![view isHiddenOrHasHiddenAncestor] &&
142           [view window] &&
143           [[view window] isVisible]);
144 }
145
146 bool IsSwipeTrackingFromScrollEventsEnabled() {
147   return NSEvent.swipeTrackingFromScrollEventsEnabled;
148 }
149
150 NSWindow* GetActiveWindow() {
151   return [NSApp keyWindow];
152 }
153
154 }  // namespace platform_util