[M85 Dev][EFL] Fix errors to generate ninja files
[platform/framework/web/chromium-efl.git] / chrome / browser / platform_util_win.cc
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
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 #include <windows.h>  // Must be in front of other Windows header files.
8
9 #include <commdlg.h>
10 #include <dwmapi.h>
11 #include <shellapi.h>
12 #include <shlobj.h>
13 #include <stddef.h>
14 #include <wrl/client.h>
15
16 #include "base/bind.h"
17 #include "base/files/file_path.h"
18 #include "base/files/file_util.h"
19 #include "base/logging.h"
20 #include "base/stl_util.h"
21 #include "base/strings/string_util.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "base/task/post_task.h"
24 #include "base/task/thread_pool.h"
25 #include "base/threading/scoped_blocking_call.h"
26 #include "base/win/registry.h"
27 #include "base/win/scoped_co_mem.h"
28 #include "chrome/browser/platform_util_internal.h"
29 #include "content/public/browser/browser_thread.h"
30 #include "ui/base/win/shell.h"
31 #include "ui/gfx/native_widget_types.h"
32 #include "url/gurl.h"
33
34 using content::BrowserThread;
35
36 namespace platform_util {
37
38 namespace {
39
40 void ShowItemInFolderOnWorkerThread(const base::FilePath& full_path) {
41   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
42                                                 base::BlockingType::MAY_BLOCK);
43   base::FilePath dir = full_path.DirName().AsEndingWithSeparator();
44   // ParseDisplayName will fail if the directory is "C:", it must be "C:\\".
45   if (dir.empty())
46     return;
47
48   Microsoft::WRL::ComPtr<IShellFolder> desktop;
49   HRESULT hr = SHGetDesktopFolder(desktop.GetAddressOf());
50   if (FAILED(hr))
51     return;
52
53   base::win::ScopedCoMem<ITEMIDLIST> dir_item;
54   hr = desktop->ParseDisplayName(NULL, NULL,
55                                  const_cast<wchar_t *>(dir.value().c_str()),
56                                  NULL, &dir_item, NULL);
57   if (FAILED(hr))
58     return;
59
60   base::win::ScopedCoMem<ITEMIDLIST> file_item;
61   hr = desktop->ParseDisplayName(NULL, NULL,
62       const_cast<wchar_t *>(full_path.value().c_str()),
63       NULL, &file_item, NULL);
64   if (FAILED(hr))
65     return;
66
67   const ITEMIDLIST* highlight[] = {file_item};
68
69   hr =
70       SHOpenFolderAndSelectItems(dir_item, base::size(highlight), highlight, 0);
71   if (FAILED(hr)) {
72     // On some systems, the above call mysteriously fails with "file not
73     // found" even though the file is there.  In these cases, ShellExecute()
74     // seems to work as a fallback (although it won't select the file).
75     if (hr == ERROR_FILE_NOT_FOUND) {
76       ShellExecute(NULL, L"open", dir.value().c_str(), NULL, NULL, SW_SHOW);
77     } else {
78       LOG(WARNING) << " " << __func__ << "(): Can't open full_path = \""
79                    << full_path.value() << "\""
80                    << " hr = " << logging::SystemErrorCodeToString(hr);
81     }
82   }
83 }
84
85 void OpenExternalOnWorkerThread(const GURL& url) {
86   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
87                                                 base::BlockingType::MAY_BLOCK);
88   // Quote the input scheme to be sure that the command does not have
89   // parameters unexpected by the external program. This url should already
90   // have been escaped.
91   std::string escaped_url = url.spec();
92   escaped_url.insert(0, "\"");
93   escaped_url += "\"";
94
95   // According to Mozilla in uriloader/exthandler/win/nsOSHelperAppService.cpp:
96   // "Some versions of windows (Win2k before SP3, Win XP before SP1) crash in
97   // ShellExecute on long URLs (bug 161357 on bugzilla.mozilla.org). IE 5 and 6
98   // support URLS of 2083 chars in length, 2K is safe."
99   //
100   // It may be possible to increase this. https://crbug.com/727909
101   const size_t kMaxUrlLength = 2048;
102   if (escaped_url.length() > kMaxUrlLength)
103     return;
104
105   if (reinterpret_cast<ULONG_PTR>(ShellExecuteA(NULL, "open",
106                                                 escaped_url.c_str(), NULL, NULL,
107                                                 SW_SHOWNORMAL)) <= 32) {
108     // On failure, it may be good to display a message to the user.
109     // https://crbug.com/727913
110     return;
111   }
112 }
113
114 }  // namespace
115
116 void ShowItemInFolder(Profile* profile, const base::FilePath& full_path) {
117   base::ThreadPool::CreateCOMSTATaskRunner(
118       {base::MayBlock(), base::TaskPriority::USER_BLOCKING})
119       ->PostTask(FROM_HERE,
120                  base::BindOnce(&ShowItemInFolderOnWorkerThread, full_path));
121 }
122
123 namespace internal {
124
125 void PlatformOpenVerifiedItem(const base::FilePath& path, OpenItemType type) {
126   // May result in an interactive dialog.
127   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
128                                                 base::BlockingType::MAY_BLOCK);
129   switch (type) {
130     case OPEN_FILE:
131       ui::win::OpenFileViaShell(path);
132       break;
133
134     case OPEN_FOLDER:
135       ui::win::OpenFolderViaShell(path);
136       break;
137   }
138 }
139
140 }  // namespace internal
141
142 void OpenExternal(Profile* profile, const GURL& url) {
143   DCHECK_CURRENTLY_ON(BrowserThread::UI);
144
145   base::ThreadPool::CreateCOMSTATaskRunner(
146       {base::MayBlock(), base::TaskPriority::USER_BLOCKING})
147       ->PostTask(FROM_HERE, base::BindOnce(&OpenExternalOnWorkerThread, url));
148 }
149
150 }  // namespace platform_util