5
5
6
6
#include " brave/browser/brave_shell_integration_win.h"
7
7
8
- #include < shlobj.h>
9
- #include < wrl/client.h>
10
-
11
8
#include < memory>
12
9
#include < string>
13
10
#include < tuple>
21
18
#include " base/strings/string_util.h"
22
19
#include " base/task/thread_pool.h"
23
20
#include " base/win/shortcut.h"
24
- #include " base/win/windows_version.h"
25
21
#include " chrome/browser/browser_process.h"
26
22
#include " chrome/browser/profiles/profile.h"
27
23
#include " chrome/browser/profiles/profile_attributes_entry.h"
30
26
#include " chrome/browser/shell_integration_win.h"
31
27
#include " chrome/installer/util/install_util.h"
32
28
#include " chrome/installer/util/shell_util.h"
29
+ #include " chrome/installer/util/taskbar_util.h"
33
30
#include " content/public/browser/browser_thread.h"
34
31
#include " third_party/abseil-cpp/absl/types/optional.h"
35
32
@@ -106,120 +103,13 @@ absl::optional<ScopedShortcutFile> GetShortcutPath(
106
103
return absl::optional<ScopedShortcutFile>(shortcut_path);
107
104
}
108
105
109
- // NOTE: Below Pin/IsPin method is copied lastest chromium.
110
- // Delete and use upstreams one when it's available from our trunk.
111
-
112
- // ScopedPIDLFromPath class, and the idea of using IPinnedList3::Modify,
113
- // are thanks to Gee Law <https://geelaw.blog/entries/msedge-pins/>
114
- class ScopedPIDLFromPath {
115
- public:
116
- explicit ScopedPIDLFromPath (PCWSTR path)
117
- : p_id_list_(ILCreateFromPath(path)) {}
118
- ~ScopedPIDLFromPath () {
119
- if (p_id_list_)
120
- ILFree (p_id_list_);
121
- }
122
- PIDLIST_ABSOLUTE Get () const { return p_id_list_; }
123
-
124
- private:
125
- PIDLIST_ABSOLUTE const p_id_list_;
126
- };
127
-
128
- enum class PinnedListModifyCaller { kExplorer = 4 };
129
-
130
- constexpr GUID CLSID_TaskbandPin = {
131
- 0x90aa3a4e ,
132
- 0x1cba ,
133
- 0x4233 ,
134
- {0xb8 , 0xbb , 0x53 , 0x57 , 0x73 , 0xd4 , 0x84 , 0x49 }};
135
-
136
- // Undocumented COM interface for manipulating taskbar pinned list.
137
- class __declspec (uuid(" 0DD79AE2-D156-45D4-9EEB-3B549769E940" )) IPinnedList3
138
- : public IUnknown {
139
- public:
140
- virtual HRESULT STDMETHODCALLTYPE EnumObjects () = 0 ;
141
- virtual HRESULT STDMETHODCALLTYPE GetPinnableInfo () = 0 ;
142
- virtual HRESULT STDMETHODCALLTYPE IsPinnable () = 0 ;
143
- virtual HRESULT STDMETHODCALLTYPE Resolve () = 0 ;
144
- virtual HRESULT STDMETHODCALLTYPE LegacyModify () = 0 ;
145
- virtual HRESULT STDMETHODCALLTYPE GetChangeCount () = 0 ;
146
- virtual HRESULT STDMETHODCALLTYPE IsPinned (PCIDLIST_ABSOLUTE) = 0 ;
147
- virtual HRESULT STDMETHODCALLTYPE GetPinnedItem () = 0 ;
148
- virtual HRESULT STDMETHODCALLTYPE GetAppIDForPinnedItem () = 0 ;
149
- virtual HRESULT STDMETHODCALLTYPE ItemChangeNotify () = 0 ;
150
- virtual HRESULT STDMETHODCALLTYPE UpdateForRemovedItemsAsNecessary () = 0 ;
151
- virtual HRESULT STDMETHODCALLTYPE PinShellLink () = 0 ;
152
- virtual HRESULT STDMETHODCALLTYPE GetPinnedItemForAppID () = 0 ;
153
- virtual HRESULT STDMETHODCALLTYPE Modify (PCIDLIST_ABSOLUTE unpin,
154
- PCIDLIST_ABSOLUTE pin,
155
- PinnedListModifyCaller caller) = 0 ;
156
- };
157
-
158
- // Returns the taskbar pinned list if successful, an empty ComPtr otherwise.
159
- Microsoft::WRL::ComPtr<IPinnedList3> GetTaskbarPinnedList () {
160
- if (base::win::GetVersion () < base::win::Version::WIN10_RS5)
161
- return nullptr ;
162
-
163
- Microsoft::WRL::ComPtr<IPinnedList3> pinned_list;
164
- if (FAILED (CoCreateInstance (CLSID_TaskbandPin, nullptr , CLSCTX_INPROC_SERVER,
165
- IID_PPV_ARGS (&pinned_list)))) {
166
- return nullptr ;
167
- }
168
-
169
- return pinned_list;
170
- }
171
-
172
- void PinShortcutWin10 (const base::FilePath& shortcut) {
173
- Microsoft::WRL::ComPtr<IPinnedList3> pinned_list = GetTaskbarPinnedList ();
174
- if (!pinned_list)
175
- return ;
176
-
177
- ScopedPIDLFromPath item_id_list (shortcut.value ().data ());
178
- pinned_list->Modify (nullptr , item_id_list.Get (),
179
- PinnedListModifyCaller::kExplorer );
180
- }
181
-
182
- absl::optional<bool > IsShortcutPinnedWin10 (const base::FilePath& shortcut) {
183
- Microsoft::WRL::ComPtr<IPinnedList3> pinned_list = GetTaskbarPinnedList ();
184
- if (!pinned_list.Get ())
185
- return absl::nullopt;
186
-
187
- ScopedPIDLFromPath item_id_list (shortcut.value ().data ());
188
- HRESULT hr = pinned_list->IsPinned (item_id_list.Get ());
189
- // S_OK means `shortcut` is pinned, S_FALSE mean it's not pinned.
190
- return SUCCEEDED (hr) ? absl::optional<bool >(hr == S_OK) : absl::nullopt;
191
- }
192
-
193
- bool IsShortcutPinned (const ShellUtil::ShortcutProperties& properties) {
194
- // Generate the shortcut to check pin state.
195
- absl::optional<ScopedShortcutFile> shortcut_path =
196
- GetShortcutPath (ExtractShortcutNameFromProperties (properties));
197
- if (!shortcut_path) {
198
- LOG (ERROR) << __func__ << " failed to get shortcut path" ;
199
- return false ;
200
- }
201
-
202
- if (!CreateShortcut (properties, shortcut_path->file_path ())) {
203
- LOG (ERROR) << __func__ << " Failed to create shortcut" ;
204
- return false ;
205
- }
206
-
207
- // Check pin state with newly created shortcut.
208
- auto pinned = IsShortcutPinnedWin10 (shortcut_path->file_path ());
209
- if (!pinned) {
210
- LOG (ERROR) << __func__ << " Can't use pin method." ;
211
- return false ;
212
- }
213
-
214
- return pinned.value ();
215
- }
216
-
217
106
// All args could be empty when we want to pin default profile's shortcut.
218
- void PinToTaskbarImpl (const base::FilePath& profile_path,
107
+ bool PinToTaskbarImpl (const base::FilePath& profile_path,
219
108
const std::u16string& profile_name,
220
109
const std::wstring& aumid) {
221
110
base::FilePath chrome_exe;
222
- base::PathService::Get (base::FILE_EXE, &chrome_exe);
111
+ if (!base::PathService::Get (base::FILE_EXE, &chrome_exe))
112
+ return false ;
223
113
224
114
ShellUtil::ShortcutProperties properties (ShellUtil::CURRENT_USER);
225
115
ShellUtil::AddDefaultShortcutProperties (chrome_exe, &properties);
@@ -243,131 +133,89 @@ void PinToTaskbarImpl(const base::FilePath& profile_path,
243
133
GetShortcutPath (ExtractShortcutNameFromProperties (properties));
244
134
if (!shortcut_path) {
245
135
LOG (ERROR) << __func__ << " failed to get shortcut path" ;
246
- return ;
136
+ return false ;
247
137
}
248
138
249
139
if (!CreateShortcut (properties, shortcut_path->file_path ())) {
250
140
LOG (ERROR) << __func__ << " Failed to create shortcut" ;
251
- return ;
252
- }
253
-
254
- // Check pin state with newly created shortcut.
255
- auto pinned = IsShortcutPinnedWin10 (shortcut_path->file_path ());
256
- if (!pinned) {
257
- LOG (ERROR) << __func__ << " Can't use pin method." ;
258
- return ;
259
- }
260
-
261
- // Don't try to pin again when it's already pinned.
262
- if (pinned.value ())
263
- return ;
264
-
265
- PinShortcutWin10 (shortcut_path->file_path ());
266
- }
267
-
268
- bool HasTaskbarAnyPinnedBraveShortcuts (
269
- const std::vector<std::tuple<base::FilePath, std::u16string, std::wstring>>&
270
- profile_attrs) {
271
- base::FilePath chrome_exe;
272
- base::PathService::Get (base::FILE_EXE, &chrome_exe);
273
-
274
- ShellUtil::ShortcutProperties properties (ShellUtil::CURRENT_USER);
275
- ShellUtil::AddDefaultShortcutProperties (chrome_exe, &properties);
276
- for (const auto & attr : profile_attrs) {
277
- const auto profile_path = std::get<0 >(attr);
278
- const auto profile_name = std::get<1 >(attr);
279
- const auto profile_aumid = std::get<2 >(attr);
280
- if (!profile_path.empty ()) {
281
- properties.set_arguments (
282
- profiles::internal::CreateProfileShortcutFlags (profile_path));
283
- properties.set_shortcut_name (
284
- profiles::internal::GetShortcutFilenameForProfile (profile_name));
285
- properties.set_app_id (profile_aumid);
286
- }
287
-
288
- if (IsShortcutPinned (properties))
289
- return true ;
141
+ return false ;
290
142
}
291
143
292
- return false ;
144
+ return PinShortcutToTaskbar (shortcut_path-> file_path ()) ;
293
145
}
294
146
295
- void DoPinToTaskbar (Profile* profile) {
147
+ void DoPinToTaskbar (const base::FilePath& profile_path,
148
+ base::OnceCallback<void (bool )> callback) {
296
149
DCHECK_CURRENTLY_ON (content::BrowserThread::UI);
297
150
298
- base::FilePath profile_path;
299
151
std::u16string profile_name;
300
152
std::wstring aumid;
301
- if (profile ) {
153
+ if (!profile_path. empty () ) {
302
154
ProfileManager* profile_manager = g_browser_process->profile_manager ();
303
155
ProfileAttributesEntry* entry =
304
156
profile_manager->GetProfileAttributesStorage ()
305
- .GetProfileAttributesWithPath (profile->GetPath ());
306
- profile_path = profile->GetPath ();
157
+ .GetProfileAttributesWithPath (profile_path);
307
158
profile_name = entry->GetName ();
308
159
aumid = shell_integration::win::GetAppUserModelIdForBrowser (profile_path);
309
160
}
310
161
311
162
base::ThreadPool::CreateCOMSTATaskRunner ({base::MayBlock ()})
312
- ->PostTask (FROM_HERE, base::BindOnce (&PinToTaskbarImpl, profile_path,
313
- profile_name, aumid));
163
+ ->PostTaskAndReplyWithResult (
164
+ FROM_HERE,
165
+ base::BindOnce (&PinToTaskbarImpl, profile_path, profile_name, aumid),
166
+ std::move (callback));
314
167
}
315
168
316
- bool CanPinToTaskbar () {
317
- base::FilePath chrome_exe;
318
- if (!base::PathService::Get (base::FILE_EXE, &chrome_exe))
319
- return false ;
169
+ } // namespace
320
170
321
- // TODO(simonhong): Support win7/8
322
- if (base::win::GetVersion () < base::win::Version::WIN10_RS5)
323
- return false ;
171
+ namespace shell_integration ::win {
324
172
325
- return true ;
326
- }
173
+ void PinToTaskbar (Profile* profile,
174
+ base::OnceCallback<void (bool )> result_callback) {
175
+ DCHECK_CURRENTLY_ON (content::BrowserThread::UI);
327
176
328
- } // namespace
177
+ if (!CanPinShortcutToTaskbar ()) {
178
+ std::move (result_callback).Run (false );
179
+ return ;
180
+ }
329
181
330
- namespace shell_integration ::win {
182
+ base::FilePath profile_path;
183
+ if (profile)
184
+ profile_path = profile->GetPath ();
331
185
332
- void PinToTaskbar (Profile* profile) {
333
- // Disable pin-to-taskabar uitll we have checkbox to ask the user to use it.
334
- return ;
186
+ // TODO(simonhong): handle connection error state if caller wants.
187
+ GetIsPinnedToTaskbarState (
188
+ base::DoNothing (),
189
+ base::BindOnce (
190
+ [](const base::FilePath& profile_path,
191
+ base::OnceCallback<void (bool )> result_callback, bool succeeded,
192
+ bool is_pinned_to_taskbar) {
193
+ if (succeeded && is_pinned_to_taskbar) {
194
+ // Early return. Already pinned.
195
+ std::move (result_callback).Run (true );
196
+ return ;
197
+ }
198
+ DoPinToTaskbar (profile_path, std::move (result_callback));
199
+ },
200
+ std::move (profile_path), std::move (result_callback)));
201
+ }
335
202
203
+ void IsShortcutPinned (base::OnceCallback<void (bool )> result_callback) {
336
204
DCHECK_CURRENTLY_ON (content::BrowserThread::UI);
337
205
338
- if (!CanPinToTaskbar ())
206
+ if (!CanPinShortcutToTaskbar ()) {
207
+ std::move (result_callback).Run (false );
339
208
return ;
340
-
341
- // At the very early stage, |g_browser_process| or its profile_manager
342
- // are not initialzied yet. In that case, skip checking existing pin state.
343
- std::vector<std::tuple<base::FilePath, std::u16string, std::wstring>>
344
- profile_attrs;
345
- // Gather data that is available on UI thread and pass it.
346
- if (g_browser_process && g_browser_process->profile_manager ()) {
347
- for (const auto * entry : g_browser_process->profile_manager ()
348
- ->GetProfileAttributesStorage ()
349
- .GetAllProfilesAttributes ()) {
350
- profile_attrs.push_back (
351
- std::make_tuple (entry->GetPath (), entry->GetName (),
352
- win::GetAppUserModelIdForBrowser (entry->GetPath ())));
353
- }
354
209
}
355
210
356
- base::ThreadPool::CreateCOMSTATaskRunner ({base::MayBlock ()})
357
- ->PostTaskAndReplyWithResult (
358
- FROM_HERE,
359
- base::BindOnce (&HasTaskbarAnyPinnedBraveShortcuts,
360
- std::move (profile_attrs)),
361
- base::BindOnce (
362
- [](Profile* profile, bool has_pin) {
363
- if (has_pin) {
364
- VLOG (2 ) << " Taskbar has already pinned brave shortcuts" ;
365
- return ;
366
- }
367
- DoPinToTaskbar (profile);
368
- },
369
- profile));
370
- return ;
211
+ GetIsPinnedToTaskbarState (
212
+ base::DoNothing (),
213
+ base::BindOnce (
214
+ [](base::OnceCallback<void (bool )> result_callback, bool succeeded,
215
+ bool is_pinned_to_taskbar) {
216
+ std::move (result_callback).Run (succeeded && is_pinned_to_taskbar);
217
+ },
218
+ std::move (result_callback)));
371
219
}
372
220
373
221
} // namespace shell_integration::win
0 commit comments