sbPlaylistCommandsHelper.cpp
Go to the documentation of this file.
1 /*
2  *=BEGIN SONGBIRD GPL
3  *
4  * This file is part of the Songbird web player.
5  *
6  * Copyright(c) 2005-2011 POTI, Inc.
7  * http://www.songbirdnest.com
8  *
9  * This file may be licensed under the terms of of the
10  * GNU General Public License Version 2 (the ``GPL'').
11  *
12  * Software distributed under the License is distributed
13  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
14  * express or implied. See the GPL for the specific language
15  * governing rights and limitations.
16  *
17  * You should have received a copy of the GPL along with this
18  * program. If not, go to http://www.gnu.org/licenses/gpl.html
19  * or write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  *
22  *=END SONGBIRD GPL
23  */
24 
31 
32 #include "nsCOMPtr.h"
33 #include "nsComponentManagerUtils.h"
34 #include "nsServiceManagerUtils.h"
35 #include <nsICategoryManager.h>
36 
37 #include "nsEnumeratorUtils.h"
38 #include "nsArrayEnumerator.h"
39 
40 #include <nsStringGlue.h>
41 #include <sbStringUtils.h>
42 
44 #include <sbDebugUtils.h>
45 
46 #define SB_MENU_HOST "menu"
47 #define SB_TOOLBAR_HOST "toolbar"
48 
51 
52 //-----------------------------------------------------------------------------
53 /* Class used to specify a visibility callback function that makes a playlist
54  * command only visible in the location specified by the param aVisibleHost
55  */
57 {
58  private:
59  nsString mVisibleHost;
60 
61  public:
64  sbPlaylistCommandsVisibility(const char* aVisibleHost);
66 };
67 
69  (const char* aVisibleHost)
70 {
71  mVisibleHost = NS_ConvertASCIItoUTF16(aVisibleHost);
72 }
73 
75 {
76 }
77 
78 NS_IMETHODIMP
79 sbPlaylistCommandsVisibility::HandleCallback
81  const nsAString &aHost,
82  const nsAString &aData,
83  PRBool *_retval)
84 {
85  NS_ENSURE_ARG_POINTER(aContext);
86  NS_ENSURE_ARG_POINTER(_retval);
87  nsString host(aHost);
88  *_retval = (host.Equals(mVisibleHost));
89  return NS_OK;
90 }
91 
94 
95 //-----------------------------------------------------------------------------
97 {
99 }
100 
101 //-----------------------------------------------------------------------------
102 /* virtual */ sbPlaylistCommandsHelper::~sbPlaylistCommandsHelper()
103 {
104 }
105 
106 //-----------------------------------------------------------------------------
107 /* sbIPlaylistCommandsHelper.idl, createCommandObjectForAction */
108 NS_IMETHODIMP
109 sbPlaylistCommandsHelper::CreateCommandObjectForAction
110  (const nsAString &aCommandId,
111  const nsAString &aLabel,
112  const nsAString &aTooltipText,
114  sbIPlaylistCommandsBuilder **_retval)
115 {
116  NS_ENSURE_ARG_POINTER(aCallback);
117  NS_ENSURE_ARG_POINTER(_retval);
118  NS_ENSURE_TRUE(!aCommandId.IsEmpty(), NS_ERROR_INVALID_ARG);
119  NS_ENSURE_TRUE(!aLabel.IsEmpty(), NS_ERROR_INVALID_ARG);
120 
121  TRACE_FUNCTION("creating commandobject id:\'%s\', label:\'%s\'",
122  NS_ConvertUTF16toUTF8(aCommandId).get(),
123  NS_ConvertUTF16toUTF8(aLabel).get());
124 
125  nsresult rv;
126  nsCOMPtr<sbIPlaylistCommandsBuilder> newCommand =
127  do_CreateInstance("@songbirdnest.com/Songbird/PlaylistCommandsBuilder;1",
128  &rv);
129  NS_ENSURE_SUCCESS(rv, rv);
130 
131  // set the id of the newly created playlist command
132  rv = newCommand->Init(aCommandId);
133  NS_ENSURE_SUCCESS(rv, rv);
134 
135  // append an action to the created playlist command with the same id
136  rv = newCommand->AppendAction(SBVoidString(),
137  aCommandId,
138  aLabel,
139  aTooltipText,
140  aCallback);
141  NS_ENSURE_SUCCESS(rv, rv);
142 
143  NS_ADDREF(*_retval = newCommand);
144  return NS_OK;
145 }
146 
147 //-----------------------------------------------------------------------------
148 /* Helper method that handles adding command objects to a medialist's
149  * root commands such that it shows up for the servicepane menu for the
150  * applicable medialist(s)
151  * This method was implemented with the intention that one of aMediaListGUID
152  * or aMediaListType is null */
153 nsresult
154 sbPlaylistCommandsHelper::AddToServicePane(const nsAString &aMediaListGUID,
155  const nsAString &aMediaListType,
156  sbIPlaylistCommands *aCommandObject)
157 {
158  /* When adding a playlist command to be displayed in the service pane menu
159  * the aCommandObject param is duplicated and the duplicate is registered
160  * to the service pane menu.
161  * This is done because RegisterPlaylistCommandsMediaList
162  * (the function to add a playlist command to a service pane menu)
163  * registers the param command object in a separate, servicepane-only map
164  * (distinct from that used by RegisterPlaylistCommandsMediaItem).
165  * The duplication means that no object added through this API should be
166  * present in both maps, hopefully making modifications more obvious and
167  * side effects less common.
168  */
169 
170  nsresult rv;
171  nsCOMPtr<sbIPlaylistCommandsManager> cmdsMgr =
173  NS_ENSURE_SUCCESS(rv, rv);
174 
175  nsCOMPtr<sbIPlaylistCommands> dupCommand;
176  rv = aCommandObject->Duplicate(getter_AddRefs(dupCommand));
177  NS_ENSURE_SUCCESS(rv, rv);
178 
179  rv = dupCommand->SetTargetFlags
181  NS_ENSURE_SUCCESS(rv, rv);
182 
183  // RegisterPlaylistCommandsMediaList is for the service pane
184  rv = cmdsMgr->RegisterPlaylistCommandsMediaList(aMediaListGUID,
185  aMediaListType,
186  dupCommand);
187  NS_ENSURE_SUCCESS(rv, rv);
188  return NS_OK;
189 }
190 
191 //-----------------------------------------------------------------------------
192 /* Helper method that handles adding command objects to a medialist's
193  * root commands such that it shows up in the context menu for mediaitems in
194  * the applicable medialist(s)
195  * This method was implemented with the intention that one of aMediaListGUID
196  * or aMediaListType is null */
197 nsresult
198 sbPlaylistCommandsHelper::AddToMediaItemContextMenu
199  (const nsAString &aMediaListGUID,
200  const nsAString &aMediaListType,
201  sbIPlaylistCommands *aCommandObject)
202 {
203  nsresult rv;
204  nsCOMPtr<sbIPlaylistCommandsManager> cmdsMgr =
206  NS_ENSURE_SUCCESS(rv, rv);
207 
208  nsCOMPtr<sbIPlaylistCommandsBuilder> commandBuilder =
209  do_QueryInterface(aCommandObject, &rv);
210  NS_ENSURE_SUCCESS(rv, rv);
211 
212  // tell aCommandObject, commandBuilder, that it will be in the context menu
213  rv = commandBuilder->SetTargetFlags
215  NS_ENSURE_SUCCESS(rv, rv);
216 
217  // set aCommandObject, commandBuilder, to only be visible in the context menu
218  rv = commandBuilder->SetVisibleCallback
220  NS_ENSURE_SUCCESS(rv, rv);
221 
222  rv = cmdsMgr->RegisterPlaylistCommandsMediaItem(aMediaListGUID,
223  aMediaListType,
224  commandBuilder);
225  NS_ENSURE_SUCCESS(rv, rv);
226  return NS_OK;
227 }
228 
229 //-----------------------------------------------------------------------------
230 /* Helper method that handles adding command objects to a medialist's
231  * root commands such that it shows up in the toolbar for
232  * the applicable medialist(s)
233  * This method was implemented with the intention that one of aMediaListGUID
234  * or aMediaListType is null */
235 nsresult
236 sbPlaylistCommandsHelper::AddToToolbar(const nsAString &aMediaListGUID,
237  const nsAString &aMediaListType,
238  sbIPlaylistCommands *aCommandObject)
239 {
240  nsresult rv;
241  nsCOMPtr<sbIPlaylistCommandsManager> cmdsMgr =
243  NS_ENSURE_SUCCESS(rv, rv);
244 
245  nsCOMPtr<sbIPlaylistCommandsBuilder> commandBuilder =
246  do_QueryInterface(aCommandObject, &rv);
247  NS_ENSURE_SUCCESS(rv, rv);
248 
249  // tell aCommandObject, now commandBuilder, that it will be in the toolbar
250  rv = commandBuilder->SetTargetFlags
252  NS_ENSURE_SUCCESS(rv, rv);
253 
254  // set aCommandObject, now commandBuilder, to only be visible in the toolbar
255  rv = commandBuilder->
256  SetVisibleCallback(new sbPlaylistCommandsVisibility(SB_TOOLBAR_HOST));
257  NS_ENSURE_SUCCESS(rv, rv);
258 
259  rv = cmdsMgr->RegisterPlaylistCommandsMediaItem(aMediaListGUID,
260  aMediaListType,
261  commandBuilder);
262  NS_ENSURE_SUCCESS(rv, rv);
263  return NS_OK;
264 }
265 
266 //-----------------------------------------------------------------------------
267 /* Helper method that handles adding command objects to a medialist's
268  * root commands.
269  * This method was implemented with the intention that one of aMediaListGUID
270  * or aMediaListType is null, and the command object is then registered to
271  * only one of the root commands (type and guid have their own root commands).
272  * While this function could work with both params (it would register a command
273  * object with both guid and type root commands), it is not recommended as it
274  * creates great ambiguity when modifying/removing a command object as changes
275  * to a command object registered to guid would be reflected in changes to that
276  * same command object but displayed by type (and vice versa).
277  */
278 nsresult
279 sbPlaylistCommandsHelper::AddCommandObject
280  (PRUint16 aTargetFlags,
281  const nsAString &aMediaListGUID,
282  const nsAString &aMediaListType,
283  sbIPlaylistCommands *aCommandObject)
284 {
285  NS_ENSURE_ARG_POINTER(aCommandObject);
286  nsresult rv;
287 
288  nsCOMPtr<sbIPlaylistCommandsManager> cmdsMgr =
290  NS_ENSURE_SUCCESS(rv, rv);
291 
292  // check if servicepane menu is a target
293  if (aTargetFlags &
295  {
296  rv = AddToServicePane(aMediaListGUID, aMediaListType, aCommandObject);
297  NS_ENSURE_SUCCESS(rv, rv);
298  }
299  // check if both the mediaitem context menu and the toolbar are targets
300  if ((aTargetFlags &
302  (aTargetFlags &
304  {
305  /* We handle additions to both the context menu and toolbar as a special
306  * case because, if an object is to be displayed in both these places, it
307  * doesn't require a visibility callback. That callback defaults to true,
308  * meaning the command is displayed in all places possible, which for
309  * RegisterPlaylistCommandsMediaItem are the toolbar and context menu */
310  unsigned short mediaItemMenuAndToolbar =
311  sbIPlaylistCommandsHelper::TARGET_MEDIAITEM_CONTEXT_MENU |
313 
314  rv = aCommandObject->SetTargetFlags(mediaItemMenuAndToolbar);
315  NS_ENSURE_SUCCESS(rv, rv);
316 
317  rv = cmdsMgr->RegisterPlaylistCommandsMediaItem(aMediaListGUID,
318  aMediaListType,
319  aCommandObject);
320  NS_ENSURE_SUCCESS(rv, rv);
321  }
322  else if (aTargetFlags &
323  sbIPlaylistCommandsHelper::TARGET_MEDIAITEM_CONTEXT_MENU)
324  {
325  // only the mediaitem context menu is a target for this playlist command
326  rv = AddToMediaItemContextMenu(aMediaListGUID, aMediaListType, aCommandObject);
327  NS_ENSURE_SUCCESS(rv, rv);
328  }
329  else if (aTargetFlags &
330  sbIPlaylistCommandsHelper::TARGET_TOOLBAR)
331  {
332  // only the toolbar is a target location for this playlist command
333  rv = AddToToolbar(aMediaListGUID, aMediaListType, aCommandObject);
334  NS_ENSURE_SUCCESS(rv, rv);
335  }
336  return NS_OK;
337 }
338 
339 //-----------------------------------------------------------------------------
340 /* sbIPlaylistCommandsHelper.idl, addCommandObjectForType */
341 NS_IMETHODIMP
342 sbPlaylistCommandsHelper::AddCommandObjectForType
343  (PRUint16 aTargetFlags,
344  const nsAString &aMediaListType,
345  sbIPlaylistCommands *aCommandObject)
346 {
347  NS_ENSURE_ARG_POINTER(aCommandObject);
348  nsresult rv;
349 
350 #if PR_LOGGING
351  {
352  nsString id;
353  rv = aCommandObject->GetId(id);
354  NS_ENSURE_SUCCESS(rv, rv);
355 
356  TRACE_FUNCTION("adding command with id \'%s\' to medialist type \'%s\'",
357  NS_ConvertUTF16toUTF8(id).get(),
358  NS_ConvertUTF16toUTF8(aMediaListType).get());
359  }
360 #endif /* PR_LOGGING */
361 
362  rv = AddCommandObject(aTargetFlags,
363  SBVoidString(),
364  aMediaListType,
365  aCommandObject);
366  NS_ENSURE_SUCCESS(rv, rv);
367  return NS_OK;
368 }
369 
370 //-----------------------------------------------------------------------------
371 /* sbIPlaylistCommandsHelper.idl, addCommandObjectForGUID */
372 NS_IMETHODIMP
373 sbPlaylistCommandsHelper::AddCommandObjectForGUID
374  (PRUint16 aTargetFlags,
375  const nsAString &aMediaListGUID,
376  sbIPlaylistCommands *aCommandObject)
377 {
378  NS_ENSURE_ARG_POINTER(aCommandObject);
379  nsresult rv;
380 
381 #if PR_LOGGING
382  {
383  nsString id;
384  rv = aCommandObject->GetId(id);
385  NS_ENSURE_SUCCESS(rv, rv);
386 
387  TRACE_FUNCTION("adding command with id \'%s\' to medialist guid \'%s\'",
388  NS_ConvertUTF16toUTF8(id).get(),
389  NS_ConvertUTF16toUTF8(aMediaListGUID).get());
390  }
391 #endif /* PR_LOGGING */
392 
393  rv = AddCommandObject(aTargetFlags,
394  aMediaListGUID,
395  SBVoidString(),
396  aCommandObject);
397  NS_ENSURE_SUCCESS(rv, rv);
398  return NS_OK;
399 }
400 
401 //-----------------------------------------------------------------------------
402 /* Class used to wrap a visibility callback function so that it will return
403  * false (not be visibile) for the host string (aHiddenHost) provided in the
404  * constructor and return the normal visibilty for all other cases.
405  */
407 {
408  public:
411 
412  sbPlaylistCommandsHidden(const char* aHiddenHost,
414  virtual ~sbPlaylistCommandsHidden();
415  private:
416  nsString mHiddenHost;
417  nsCOMPtr<sbIPlaylistCommandsBuilderPCCallback> mOriginalCallback;
418 };
419 
421  (const char* aHiddenHost,
423 {
424  mHiddenHost = NS_ConvertASCIItoUTF16(aHiddenHost);
425  mOriginalCallback = aCallback;
426 }
427 
429 {
430 }
431 
432 NS_IMETHODIMP
433 sbPlaylistCommandsHidden::HandleCallback
435  const nsAString &aHost,
436  const nsAString &aData,
437  PRBool *_retval)
438 {
439  NS_ENSURE_ARG_POINTER(aContext);
440  NS_ENSURE_ARG_POINTER(_retval);
441  nsString host(aHost);
442 
443  // return false if the host string being checked is the one we want to hide
444  if (host.Equals(mHiddenHost))
445  {
446  // we definitely don't want this to appear in the context menu
447  *_retval = PR_FALSE;
448  }
449  else {
450  /* for anything host string other than mHiddenHost, do what the
451  * original callback did. */
452  nsresult rv = mOriginalCallback->HandleCallback(aContext,
453  aHost,
454  aData,
455  _retval);
456  NS_ENSURE_SUCCESS(rv, rv);
457  }
458 
459  return NS_OK;
460 }
461 
464 
465 //-----------------------------------------------------------------------------
466 /* A helper function to adjust aCommandObject's flags following a remove.
467  * aCommandObject.targetFlags will not include any of those flags specified by
468  * aTargetFlags at the end of this function. Depending on our knowledge of
469  * aCommandObject's location (through aCommandObject.targetFlags at this
470  * function's start), however, aCommandObject.targetFlags may or may not
471  * accurately reflect aCommandObject's actual location at the end of this
472  * function, but it will always accurately reflect where this function is _not_.
473  */
474 nsresult
475 sbPlaylistCommandsHelper::SetRemainingFlags
476  (PRUint16 aTargetFlags,
477  sbIPlaylistCommands *aCommandObject)
478 {
479  PRUint16 commandsLocation;
480  nsresult rv = aCommandObject->GetTargetFlags(&commandsLocation);
481  NS_ENSURE_SUCCESS(rv, rv);
482 
483  if (!commandsLocation || commandsLocation == 0)
484  {
485  /* The command object doesn't know where it is, but we know where it is not
486  * Set the remaining flags to be the opposite of those that we removed,
487  * but also only set those flags that we actually use (under the umbrella
488  * of TARGET_ALL) */
489  commandsLocation = (~aTargetFlags) & sbPlaylistCommandsHelper::TARGET_ALL;
490  }
491  else {
492  /* The command object knows where it was, so we'll use that info to update.
493  * Set the remaining flags to be those that the object was present in
494  * that are not the ones that it was removed from.
495  */
496  commandsLocation = commandsLocation & (~aTargetFlags);
497  }
498  rv = aCommandObject->SetTargetFlags(commandsLocation);
499  NS_ENSURE_SUCCESS(rv, rv);
500 
501  return NS_OK;
502 }
503 
504 //-----------------------------------------------------------------------------
505 /* Helper method that handles removing command objects from a medialist's
506  * root commands.
507  * This method was implemented with the intention that one of aMediaListGUID
508  * or aMediaListType is null, and the command object is then only removed from
509  * one of the root commands (type and guid have their own root commands).
510  * While this function could work with both params (it would unregister
511  * aCommandObject from both guid and type root commands), it is not recommended.
512  */
513 nsresult
514 sbPlaylistCommandsHelper::RemoveCommandObject
515  (PRUint16 aTargetFlags,
516  const nsAString &aMediaListGUID,
517  const nsAString &aMediaListType,
518  sbIPlaylistCommands *aCommandObject)
519 {
520  NS_ENSURE_ARG_POINTER(aCommandObject);
521  nsresult rv;
522  nsCOMPtr<sbIPlaylistCommandsManager> cmdsMgr =
524  NS_ENSURE_SUCCESS(rv, rv);
525 
526  PRBool removeFromServicePane =
527  (aTargetFlags &
529 
530  PRBool removeFromContextMenu =
531  (aTargetFlags &
533 
534  PRBool removeFromToolbar =
535  (aTargetFlags &
537 
538  // if we want to remove from the service pane, we can do that now
539  if (removeFromServicePane)
540  {
541  /* Command objects registered to the service pane are distinct from those
542  * registered to the context menu and/or toolbar as they are stored in their
543  * own, servicepane-only map. Thus, if we want to remove from the service
544  * pane, we can do that fairly straightforwardly */
545 
546  // UnregisterPlaylistCommandsMediaList deals with the service pane
547  rv = cmdsMgr->UnregisterPlaylistCommandsMediaList(aMediaListGUID,
548  aMediaListType,
549  aCommandObject);
550  NS_ENSURE_SUCCESS(rv, rv);
551  // unregister does its own onCommandRemoved signal, so no need here
552  }
553 
554  // if we want to remove from the context menu and toolbar, we can do that now
555  if (removeFromContextMenu && removeFromToolbar)
556  {
557  /* Removing from both the context menu and toolbar is fairly straightforward
558  * because commands registered to those locations are stored in the same
559  * map. Thus, if we know we want to remove aCommandObject from both
560  * the toolbar and context menu, we can just unregister the command from
561  * that map */
562 
563  rv = cmdsMgr->UnregisterPlaylistCommandsMediaItem(aMediaListGUID,
564  aMediaListType,
565  aCommandObject);
566  NS_ENSURE_SUCCESS(rv, rv);
567  // unregister does its own onCommandRemoved signal, so no need here
568 
569  rv = SetRemainingFlags(aTargetFlags, aCommandObject);
570  NS_ENSURE_SUCCESS(rv, rv);
571  return NS_OK;
572  }
573 
574  /* We've already handled the service pane, and we don't want to remove from the
575  * context menu or the toolbar, so we are done. */
576  if (!removeFromContextMenu && !removeFromToolbar) {
577  rv = SetRemainingFlags(aTargetFlags, aCommandObject);
578  NS_ENSURE_SUCCESS(rv, rv);
579  return NS_OK;
580  }
581 
582  // at this point, we are targetting one of the context menu and toolbar
583  PRUint16 commandsLocation;
584  rv = aCommandObject->GetTargetFlags(&commandsLocation);
585  NS_ENSURE_SUCCESS(rv, rv);
586 
587  if (!commandsLocation || commandsLocation == 0)
588  {
589  /* The command object being removed does not know where it is.
590  * This is most likely because aCommandObject was added with the old,
591  * non-helper API that doesn't use these locations.
592  * This is the bad case. We know we want to remove the command from only
593  * 1 of context menu and toolbar, but we can't be sure how to proceed.
594  * Potentially, the command is present only in the place that we want
595  * to remove it from. In that case, we could safely unregister it. We
596  * don't, however, know where the command is. So we cannot safely unregister
597  *
598  * Rather, we assume that the command is present in both the context menu
599  * and toolbar, and because we only want to remove it from one we must
600  * adjust the visibility callback accordingly.
601  */
602  nsCOMPtr<sbIPlaylistCommandsBuilderPCCallback> oldCallback;
603  rv = aCommandObject->GetVisibleCallback(getter_AddRefs(oldCallback));
604  NS_ENSURE_SUCCESS(rv, rv);
605 
606  nsCOMPtr<sbIPlaylistCommandsBuilder> commandBuilder =
607  do_QueryInterface(aCommandObject,
608  &rv);
609  NS_ENSURE_SUCCESS(rv, rv);
610 
611  /* if we want to remove the command from the context menu, set our
612  * visibility callback to be hidden in the context menu. Otherwise,
613  * we want this to be removed from the toolbar, so make it hidden there */
614  nsCOMPtr<sbPlaylistCommandsHidden> visCallback =
615  (removeFromContextMenu ? new sbPlaylistCommandsHidden(SB_MENU_HOST,
616  oldCallback) :
617  new sbPlaylistCommandsHidden(SB_TOOLBAR_HOST,
618  oldCallback));
619  rv = commandBuilder->SetVisibleCallback(visCallback);
620  NS_ENSURE_SUCCESS(rv, rv);
621  rv = commandBuilder->NotifyListeners
622  (NS_LITERAL_STRING("onCommandChanged"),
623  commandBuilder);
624  }
625  else {
626  // The command object being removed knows where it is and will help us.
627  // The service pane was handled first, so we don't worry about that here.
628  PRBool isInContextMenu =
629  (commandsLocation &
631 
632  PRBool isInToolbar =
633  (commandsLocation &
635 
636  if (isInContextMenu && isInToolbar)
637  {
638  /* the command object is in two places and we want to remove it from one
639  * so we need to change it's visibility callback */
640  nsCOMPtr<sbIPlaylistCommandsBuilder> commandBuilder =
641  do_QueryInterface(aCommandObject,
642  &rv);
643  NS_ENSURE_SUCCESS(rv, rv);
644 
645  /* if we are removing from the context menu, set the visibilty to show
646  * only in the toolbar. Otherwise, we are removing from the toolbar so
647  * set the visibility to only show in the context menu */
648  nsCOMPtr<sbPlaylistCommandsVisibility> visCallback =
649  (removeFromContextMenu ? new sbPlaylistCommandsVisibility(SB_TOOLBAR_HOST) :
650  new sbPlaylistCommandsVisibility(SB_MENU_HOST));
651 
652  rv = commandBuilder->SetVisibleCallback(visCallback);
653  NS_ENSURE_SUCCESS(rv, rv);
654 
655  rv = commandBuilder->NotifyListeners
656  (NS_LITERAL_STRING("onCommandChanged"),
657  commandBuilder);
658  NS_ENSURE_SUCCESS(rv, rv);
659 
660  }
661  else if ((isInContextMenu && removeFromContextMenu) ||
662  (isInToolbar && removeFromToolbar)) {
663  /* the command object is present in one of the context menu or toolbar
664  * and we want to remove it from there, so we can unregister it */
665  rv = cmdsMgr->UnregisterPlaylistCommandsMediaItem(aMediaListGUID,
666  aMediaListType,
667  aCommandObject);
668  NS_ENSURE_SUCCESS(rv, rv);
669  // unregister does its own onCommandRemoved signal, so no need here
670  }
671  }
672  rv = SetRemainingFlags(aTargetFlags, aCommandObject);
673  NS_ENSURE_SUCCESS(rv, rv);
674 
675  return NS_OK;
676 }
677 
678 //-----------------------------------------------------------------------------
679 /* sbIPlaylistCommandsHelper.idl, removeCommandObjectForType */
680 NS_IMETHODIMP
681 sbPlaylistCommandsHelper::RemoveCommandObjectForType
682  (PRUint16 aTargetFlags,
683  const nsAString &aMediaListType,
684  sbIPlaylistCommands *aCommandObject)
685 {
686  NS_ENSURE_ARG_POINTER(aCommandObject);
687  nsresult rv;
688 
689 #if PR_LOGGING
690  {
691  nsString id;
692  rv = aCommandObject->GetId(id);
693  NS_ENSURE_SUCCESS(rv, rv);
694 
695  TRACE_FUNCTION("removing object with id \'%s\' from medialist type \'%s\'",
696  NS_ConvertUTF16toUTF8(id).get(),
697  NS_ConvertUTF16toUTF8(aMediaListType).get());
698  }
699 #endif /* PR_LOGGING */
700 
701  rv = RemoveCommandObject(aTargetFlags,
702  SBVoidString(),
703  aMediaListType,
704  aCommandObject);
705  NS_ENSURE_SUCCESS(rv, rv);
706 
707  return NS_OK;
708 }
709 
710 //-----------------------------------------------------------------------------
711 /* sbIPlaylistCommandsHelper.idl, removeCommandObjectForGUID */
712 NS_IMETHODIMP
713 sbPlaylistCommandsHelper::RemoveCommandObjectForGUID
714  (PRUint16 aTargetFlags,
715  const nsAString &aMediaListGUID,
716  sbIPlaylistCommands *aCommandObject)
717 {
718  NS_ENSURE_ARG_POINTER(aCommandObject);
719  nsresult rv;
720 
721 #if PR_LOGGING
722  {
723  nsString id;
724  rv = aCommandObject->GetId(id);
725  NS_ENSURE_SUCCESS(rv, rv);
726 
727  TRACE_FUNCTION("removing object with id \'%s\' from medialist guid \'%s\'",
728  NS_ConvertUTF16toUTF8(id).get(),
729  NS_ConvertUTF16toUTF8(aMediaListGUID).get());
730  }
731 #endif /* PR_LOGGING */
732 
733  TRACE_FUNCTION("");
734  rv = RemoveCommandObject(aTargetFlags,
735  aMediaListGUID,
736  SBVoidString(),
737  aCommandObject);
738  NS_ENSURE_SUCCESS(rv, rv);
739 
740  return NS_OK;
741 }
742 
743 //-----------------------------------------------------------------------------
744 /* A helper function to search a sbIPlaylistCommands object, aParentCommand,
745  * for a command with an id of aCommandId and return it */
746 nsresult
747 sbPlaylistCommandsHelper::GetChildCommandWithId
748  (sbIPlaylistCommands *aParentCommand,
749  const nsAString &aCommandId,
750  sbIPlaylistCommands **_retval)
751 {
752  NS_ENSURE_ARG_POINTER(aParentCommand);
753  NS_ENSURE_ARG_POINTER(_retval);
754 
755  nsString commandId(aCommandId);
756  nsCOMPtr<nsISimpleEnumerator> cmdEnum;
757 
758  /* loop through the children of the parent command to look for one with the
759  * param id */
760  nsresult rv = aParentCommand->GetChildrenCommandObjects
761  (getter_AddRefs(cmdEnum));
762  NS_ENSURE_SUCCESS(rv, rv);
763 
764  PRBool hasMore;
765  while (NS_SUCCEEDED(cmdEnum->HasMoreElements(&hasMore)) && hasMore) {
766  nsCOMPtr<sbIPlaylistCommands> next;
767  if (NS_SUCCEEDED(cmdEnum->GetNext(getter_AddRefs(next))) && next) {
768  nsString aId;
769  rv = next->GetId(aId);
770  NS_ENSURE_SUCCESS(rv, rv);
771 
772  // return the first playlist command with the param id
773  if (aId == commandId) {
774  NS_ADDREF(*_retval = next);
775  return NS_OK;
776  }
777  }
778  }
779 
780  return NS_OK;
781 }
782 
783 //-----------------------------------------------------------------------------
784 /* A helper function to search the root sbIPlaylistCommands for a medialist
785  * guid or type and return an sbIPlaylistCommands object with the param
786  * aCommandId. This method was implemented with the intention that one of
787  * aMediaListGUID or aMediaListType is null, and then only the root commands
788  * for the param provided are searched.
789  * This function can be used with both aMediaListGUID and aMediaListType
790  * params passed, and both guid and type root commands will be searched,
791  * but it is not recommended. If both params are specified, guid root
792  * commands will be searched first, followed by those for type, and the first
793  * match is returned.
794  */
795 nsresult
796 sbPlaylistCommandsHelper::GetCommandObject(PRUint16 aTargetFlag,
797  const nsAString &aMediaListGUID,
798  const nsAString &aMediaListType,
799  const nsAString &aCommandId,
800  sbIPlaylistCommands **_retval)
801 {
802  NS_ENSURE_ARG_POINTER(_retval);
803 
804  nsresult rv;
805  nsCOMPtr<sbIPlaylistCommandsManager> cmdsMgr =
807  NS_ENSURE_SUCCESS(rv, rv);
808 
809  nsCOMPtr<sbIPlaylistCommands> foundCommand = nsnull;
810  nsCOMPtr<sbIPlaylistCommands> rootCommand;
811 
812  if (aTargetFlag &
813  sbIPlaylistCommandsHelper::TARGET_SERVICEPANE_MENU)
814  {
815  // servicepane menu is target
816  rv = cmdsMgr->GetPlaylistCommandsMediaList(aMediaListGUID,
817  aMediaListType,
818  getter_AddRefs(rootCommand));
819  NS_ENSURE_SUCCESS(rv, rv);
820  }
821  else if (aTargetFlag &
822  (sbIPlaylistCommandsHelper::TARGET_MEDIAITEM_CONTEXT_MENU |
823  sbIPlaylistCommandsHelper::TARGET_TOOLBAR)) {
824  // mediaitem context menu or toolbar is target
825  rv = cmdsMgr->GetPlaylistCommandsMediaItem(aMediaListGUID,
826  aMediaListType,
827  getter_AddRefs(rootCommand));
828  NS_ENSURE_SUCCESS(rv, rv);
829  }
830 
831  if (rootCommand)
832  {
833  rv = GetChildCommandWithId(rootCommand,
834  aCommandId,
835  getter_AddRefs(foundCommand));
836  NS_ENSURE_SUCCESS(rv, rv);
837  }
838 
839  /* We found a command, but we need to make sure that it's actually where the
840  * caller asked us to look for it, i.e. in a place included in aTargetFlags.
841  *
842  * We'll try to get the targetFlags of our found command to confirm, but
843  * it is possible that the command won't have them. So check them if we can,
844  * but if it doesn't have the flags just return it.
845  */
846  if (foundCommand)
847  {
848  PRUint16 foundFlags;
849  rv = foundCommand->GetTargetFlags(&foundFlags);
850  NS_ENSURE_SUCCESS(rv, rv);
851 
852  if (foundFlags > 0 && (foundFlags & aTargetFlag) == 0)
853  {
854  foundCommand = nsnull;
855  }
856  }
857  NS_IF_ADDREF(*_retval = foundCommand);
858  return NS_OK;
859 }
860 
861 //-----------------------------------------------------------------------------
862 /* sbIPlaylistCommandsHelper.idl, getCommandObjectForType */
863 NS_IMETHODIMP
864 sbPlaylistCommandsHelper::GetCommandObjectForType
865  (PRUint16 aTargetFlag,
866  const nsAString &aMediaListType,
867  const nsAString &aCommandId,
868  sbIPlaylistCommands **_retval)
869 {
870  NS_ENSURE_ARG_POINTER(_retval);
871  nsresult rv;
872 
873  TRACE_FUNCTION("getting object with id \'%s\' from medialist type \'%s\'",
874  NS_ConvertUTF16toUTF8(aCommandId).get(),
875  NS_ConvertUTF16toUTF8(aMediaListType).get());
876 
877  nsCOMPtr<sbIPlaylistCommands> foundCommand;
878  rv = GetCommandObject(aTargetFlag,
879  SBVoidString(),
880  aMediaListType,
881  aCommandId,
882  getter_AddRefs(foundCommand));
883  NS_ENSURE_SUCCESS(rv, rv);
884 
885  NS_IF_ADDREF(*_retval = foundCommand);
886  return NS_OK;
887 }
888 
889 //-----------------------------------------------------------------------------
890 /* sbIPlaylistCommandsHelper.idl, getCommandObjectForGUID */
891 NS_IMETHODIMP
892 sbPlaylistCommandsHelper::GetCommandObjectForGUID
893  (PRUint16 aTargetFlag,
894  const nsAString &aMediaListGUID,
895  const nsAString &aCommandId,
896  sbIPlaylistCommands **_retval)
897 {
898  NS_ENSURE_ARG_POINTER(_retval);
899  nsresult rv;
900 
901  TRACE_FUNCTION("getting object with id \'%s\' from medialist guid \'%s\'",
902  NS_ConvertUTF16toUTF8(aCommandId).get(),
903  NS_ConvertUTF16toUTF8(aMediaListGUID).get());
904 
905  nsCOMPtr<sbIPlaylistCommands> foundCommand;
906  rv = GetCommandObject(aTargetFlag,
907  aMediaListGUID,
908  SBVoidString(),
909  aCommandId,
910  getter_AddRefs(foundCommand));
911  NS_ENSURE_SUCCESS(rv, rv);
912 
913  NS_IF_ADDREF(*_retval = foundCommand);
914  return NS_OK;
915 }
916 
#define SONGBIRD_PlaylistCommandsManager_CONTRACTID
A helper used to construct sbIPlaylistCommands interfaces.
#define SB_PRLOG_SETUP(x)
Definition: sbDebugUtils.h:115
return NS_OK
NS_IMPL_THREADSAFE_ISUPPORTS1(sbPlaylistCommandsVisibility, sbIPlaylistCommandsBuilderPCCallback)
menuItem id
Definition: FeedWriter.js:971
NS_DECL_SBIPLAYLISTCOMMANDSBUILDERPCCALLBACK
_updateCookies aHost
virtual ~sbPlaylistCommandsVisibility()
The interface for giving context to playlist builder callbacks.
A callback interface used to receive callbacks from an sbIPlaylistCommandsBuilder object relating to ...
const unsigned short TARGET_TOOLBAR
A flag referring to the toolbar at the bottom of a medialist view.
const unsigned short TARGET_ALL
A convenience flag referring to all locations that a sbIPlaylistCommands object can appear...
const unsigned short TARGET_MEDIAITEM_CONTEXT_MENU
A flag referring to the context menu that appears from mediaitems displayed in the medialist...
An interface used to receive generic callbacks from an sbIPlaylistCommandsBuilder object...
#define SB_TOOLBAR_HOST
A helper service to add and remove playlistCommands.
Songbird PlaylistCommandsManager Component Definition.
#define SB_MENU_HOST
#define TRACE_FUNCTION(...)
Definition: sbDebugUtils.h:118
An interface that represents the set of command buttons and context menu items available on a display...
sbPlaylistCommandsHidden(const char *aHiddenHost, sbIPlaylistCommandsBuilderPCCallback *aCallback)
StringArrayEnumerator prototype hasMore
const unsigned short TARGET_SERVICEPANE_MENU
A flag referring to the context menu that appears from the service pane node.
Songbird PlaylistCommandsHelper Component Definition.
sbPlaylistCommandsVisibility(const char *aVisibleHost)
_updateTextAndScrollDataForFrame aData
function next()