| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2014 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/ui/views/apps/jumplist_updater_win.h" |
| 6 |
| 7 #include <propvarutil.h> |
| 8 #include <shobjidl.h> |
| 9 #include <windows.h> |
| 10 // This include needs to go out of order to prevent compilation errors because |
| 11 // propidl.h does not check whether PID_FIRST_USABLE is already defined. |
| 12 #include <propkey.h> |
| 13 |
| 14 #include "base/command_line.h" |
| 15 #include "base/path_service.h" |
| 16 #include "base/win/scoped_comptr.h" |
| 17 #include "base/win/scoped_propvariant.h" |
| 18 #include "base/win/windows_version.h" |
| 19 #include "chrome/browser/profiles/profile.h" |
| 20 #include "chrome/common/chrome_constants.h" |
| 21 #include "chrome/common/chrome_switches.h" |
| 22 |
| 23 namespace { |
| 24 |
| 25 void AddShellLink(base::win::ScopedComPtr<IObjectCollection> collection, |
| 26 const std::wstring& application, |
| 27 const std::wstring& switches, |
| 28 const JumpListUpdater::ListItem& list_item) { |
| 29 base::win::ScopedComPtr<IShellLink> link; |
| 30 HRESULT result = link.CreateInstance(CLSID_ShellLink, NULL, |
| 31 CLSCTX_INPROC_SERVER); |
| 32 if (FAILED(result)) |
| 33 return; |
| 34 |
| 35 // Set the application path to invoke for each link. |
| 36 result = link->SetPath(application.c_str()); |
| 37 if (FAILED(result)) |
| 38 return; |
| 39 |
| 40 // Set the command line args. |
| 41 std::wstring arguments(switches); |
| 42 if (!list_item.command_line_args.empty()) { |
| 43 arguments.push_back(L' '); |
| 44 arguments += list_item.command_line_args; |
| 45 } |
| 46 if (!arguments.empty()) { |
| 47 result = link->SetArguments(arguments.c_str()); |
| 48 if (FAILED(result)) |
| 49 return; |
| 50 } |
| 51 |
| 52 // Set the icon. This can be allowed to fail. |
| 53 if (!list_item.icon_path.empty()) |
| 54 link->SetIconLocation(list_item.icon_path.value().c_str(), 0); |
| 55 |
| 56 // Set the title. This must be added as a property. |
| 57 base::win::ScopedComPtr<IPropertyStore> property_store; |
| 58 result = link.QueryInterface(property_store.Receive()); |
| 59 if (FAILED(result)) |
| 60 return; |
| 61 |
| 62 base::win::ScopedPropVariant property_title; |
| 63 result = InitPropVariantFromString(list_item.title.c_str(), |
| 64 property_title.Receive()); |
| 65 if (FAILED(result)) |
| 66 return; |
| 67 |
| 68 result = property_store->SetValue(PKEY_Title, property_title.get()); |
| 69 if (FAILED(result)) |
| 70 return; |
| 71 |
| 72 result = property_store->Commit(); |
| 73 if (FAILED(result)) |
| 74 return; |
| 75 |
| 76 // Add this IShellLink to the given collection. |
| 77 collection->AddObject(link); |
| 78 } |
| 79 |
| 80 void AddTasks(base::win::ScopedComPtr<ICustomDestinationList> jumplist, |
| 81 const std::wstring& application, |
| 82 const std::wstring& switches, |
| 83 const std::vector<JumpListUpdater::ListItem>& items) { |
| 84 // Create a collection to store items for the "Tasks" category of the |
| 85 // jump list. |
| 86 base::win::ScopedComPtr<IObjectCollection> collection; |
| 87 HRESULT result = collection.CreateInstance(CLSID_EnumerableObjectCollection, |
| 88 NULL, CLSCTX_INPROC_SERVER); |
| 89 if (FAILED(result)) |
| 90 return; |
| 91 |
| 92 // Add list items. |
| 93 for (std::vector<JumpListUpdater::ListItem>::const_iterator it = |
| 94 items.begin(); it != items.end(); ++it) { |
| 95 AddShellLink(collection, application, switches, *it); |
| 96 } |
| 97 |
| 98 // Cast to IObjectArray and update the jump list's "Tasks". |
| 99 base::win::ScopedComPtr<IObjectArray> object_array; |
| 100 result = collection.QueryInterface(object_array.Receive()); |
| 101 if (FAILED(result)) |
| 102 return; |
| 103 |
| 104 jumplist->AddUserTasks(object_array); |
| 105 } |
| 106 |
| 107 } // namespace |
| 108 |
| 109 // static |
| 110 void JumpListUpdater::AppendArgs(const std::string& switch_string, |
| 111 const base::string16& value, |
| 112 base::string16* command_line_args) { |
| 113 DCHECK(command_line_args); |
| 114 CommandLine command_line(CommandLine::NO_PROGRAM); |
| 115 if (value.empty()) |
| 116 command_line.AppendSwitch(switch_string); |
| 117 else |
| 118 command_line.AppendSwitchNative(switch_string, value); |
| 119 |
| 120 if (!command_line_args->empty()) |
| 121 command_line_args->push_back(L' '); |
| 122 *command_line_args += command_line.GetCommandLineString(); |
| 123 } |
| 124 |
| 125 JumpListUpdater::JumpListUpdater( |
| 126 Profile* profile, |
| 127 const base::string16& app_user_model_id) |
| 128 : profile_(profile), |
| 129 app_user_model_id_(app_user_model_id) { |
| 130 PathService::Get(base::FILE_EXE, &chrome_path_); |
| 131 |
| 132 // Set up common command line switches. |
| 133 base::FilePath user_data_dir = CommandLine::ForCurrentProcess()-> |
| 134 GetSwitchValuePath(switches::kUserDataDir); |
| 135 if (!user_data_dir.empty()) |
| 136 AppendArgs(switches::kUserDataDir, |
| 137 user_data_dir.value(), |
| 138 &default_chrome_switches_); |
| 139 } |
| 140 |
| 141 JumpListUpdater::~JumpListUpdater() {} |
| 142 |
| 143 void JumpListUpdater::Update(const std::vector<ListItem>& items) { |
| 144 // Check all the preconditions for creating a jump list. |
| 145 if (chrome_path_.empty()) |
| 146 return; |
| 147 |
| 148 if (base::win::GetVersion() < base::win::VERSION_WIN7) |
| 149 return; |
| 150 |
| 151 // Create the jump list. |
| 152 base::win::ScopedComPtr<ICustomDestinationList> jumplist; |
| 153 HRESULT result = jumplist.CreateInstance(CLSID_DestinationList, NULL, |
| 154 CLSCTX_INPROC_SERVER); |
| 155 if (FAILED(result)) |
| 156 return; |
| 157 |
| 158 // Associate the jump list with this application. |
| 159 jumplist->SetAppID(app_user_model_id_.c_str()); |
| 160 |
| 161 // Start transaction to modify the jump list. |
| 162 UINT max_slots; // unused |
| 163 base::win::ScopedComPtr<IObjectArray> removed; // unused |
| 164 result = jumplist->BeginList(&max_slots, __uuidof(*removed), |
| 165 reinterpret_cast<void**>(&removed)); |
| 166 if (FAILED(result)) |
| 167 return; |
| 168 |
| 169 // Add items to the predefined "Tasks" category. |
| 170 AddTasks(jumplist, |
| 171 chrome_path_.value(), |
| 172 default_chrome_switches_, |
| 173 items); |
| 174 |
| 175 // Commit changes to the jump list. |
| 176 jumplist->CommitList(); |
| 177 } |
| OLD | NEW |