forked from amazingfate/loongoffice
There are some CrashReports in 7.6 which have DeleteItemOnIdle on the stack, but there is nothing reproducable. So I took a look... I first thought it's a MCGR regression, due to classes on the stack. But the Item involved is just random, can happen with any Item. Then I thought it may have to do with ITEM refactorings, but it happens with DeleteItemOnIdle involved, so also not the case. I already saw DeleteItemOnIdle when doing these and qualified as 'hack' in the way. already It is only on Windows and DeleteItemOnIdle is involved. This again (took a deeper look now) is an old hack to keep an SfxPoolItem 'alive' for some 'time'. For that, it triggers an async reschedule which then deletes the Item when being called. If the Item will be used after that is pure coincidence - seems to work in most cases. It seems as if for Windows the timing slightly changed for some scenarios, so a reschedule is too early. This can happen with this hack anytime. DeleteItemOnIdle is used in scenarios where SfxPoolItem* is e.g. returned, but is *not* anchored, so e.g. not member of an SfxItemSet. Or in short: Lifetime is not safe. DeleteItemOnIdle exists since 1st import, but was changed to AsyncEvent ca. 4 months ago (see 57145acf9ec47c23e307b7a5c0029d21d937cc35), so that may have caused it. It is possible that these errors happen on Windows since then. Before something more complicated was used to delete it late, but surely also not really safe. Due to ITEM refactor I have the knowledge/tooling to solve this. It will not be a 1-5 lines fix, but it is a hack and in the way for further ITEM refactor anyways. What we have nowadays is a SfxPoolItemHolder -> it's like an SfxItemSet for a single Item. It safely holds/ controls the lifetime of an SfxPoolItem. It is already used in quite some places. It helps to solve many hacks, also the ones putting Items directly to the Pool - due to there never was an alternative for that. In principle the ItemPool/ItemSet/Item paradigm was never complete without SfxPoolItemHolder. Thus I started to fix that (and remove that hack for good, sooo many changes over the years, sigh), but as said is not straightforward. Will have to change retvals of involved stuff to SfxPoolItemHolder - it's just two pointers and designed to be copied (one is a Pool, needed to cleanup when destructing). CopyConstruct/destroy just counts the RefCnt up/down, so cheap. 1st version compiling, let's check on gerrit... Corrected one error in QueryState for securitypage, also added some security features/asserts. Change-Id: Ida49fd35ca88ead84b11d93e18b978cb9e395090 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161083 Tested-by: Jenkins Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
134 lines
5.0 KiB
C++
134 lines
5.0 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
#ifndef INCLUDED_SFX2_REQUEST_HXX
|
|
#define INCLUDED_SFX2_REQUEST_HXX
|
|
|
|
#include <sal/config.h>
|
|
#include <sfx2/dllapi.h>
|
|
#include <sal/types.h>
|
|
#include <svl/itemset.hxx>
|
|
|
|
#include <memory>
|
|
|
|
class SfxPoolItem;
|
|
class SfxItemPool;
|
|
class SfxShell;
|
|
class SfxSlot;
|
|
class SfxViewFrame;
|
|
struct SfxRequest_Impl;
|
|
enum class SfxCallMode : sal_uInt16;
|
|
|
|
namespace com::sun::star::beans { struct PropertyValue; }
|
|
namespace com::sun::star::frame { class XDispatchRecorder; }
|
|
namespace com::sun::star::uno { template <class E> class Sequence; }
|
|
namespace weld { class Window; }
|
|
|
|
class SFX2_DLLPUBLIC SfxRequest final
|
|
{
|
|
friend struct SfxRequest_Impl;
|
|
|
|
sal_uInt16 nSlot;
|
|
std::unique_ptr<SfxAllItemSet> pArgs;
|
|
std::unique_ptr< SfxRequest_Impl > pImpl;
|
|
|
|
public:
|
|
SAL_DLLPRIVATE void Record_Impl( SfxShell &rSh, const SfxSlot &rSlot,
|
|
const css::uno::Reference< css::frame::XDispatchRecorder >& xRecorder,
|
|
SfxViewFrame* );
|
|
private:
|
|
SAL_DLLPRIVATE void Done_Impl( const SfxItemSet *pSet );
|
|
|
|
public:
|
|
SfxRequest( SfxViewFrame&, sal_uInt16 nSlotId );
|
|
SfxRequest( sal_uInt16 nSlot, SfxCallMode nCallMode, SfxItemPool &rPool );
|
|
SfxRequest( const SfxSlot* pSlot, const css::uno::Sequence < css::beans::PropertyValue >& rArgs,
|
|
SfxCallMode nCallMode, SfxItemPool &rPool );
|
|
SfxRequest(sal_uInt16 nSlot, SfxCallMode nCallMode, const SfxAllItemSet& rSfxArgs);
|
|
SfxRequest( sal_uInt16 nSlot, SfxCallMode nCallMode, const SfxAllItemSet& rSfxArgs, const SfxAllItemSet& rSfxInternalArgs );
|
|
SfxRequest( const SfxRequest& rOrig );
|
|
~SfxRequest();
|
|
|
|
sal_uInt16 GetSlot() const { return nSlot; }
|
|
void SetSlot(sal_uInt16 nNewSlot) { nSlot = nNewSlot; }
|
|
|
|
sal_uInt16 GetModifier() const;
|
|
void SetModifier( sal_uInt16 nModi );
|
|
void SetInternalArgs_Impl( const SfxAllItemSet& rArgs );
|
|
SAL_DLLPRIVATE const SfxItemSet* GetInternalArgs_Impl() const;
|
|
const SfxItemSet* GetArgs() const { return pArgs.get(); }
|
|
void SetArgs( const SfxAllItemSet& rArgs );
|
|
void AppendItem(const SfxPoolItem &);
|
|
void RemoveItem( sal_uInt16 nSlotId );
|
|
|
|
/** Templatized access to the individual parameters of the SfxRequest.
|
|
|
|
Use like: const SfxInt32Item *pPosItem = rReq.GetArg<SfxInt32Item>(SID_POS);
|
|
*/
|
|
template<class T> const T* GetArg(sal_uInt16 nSlotId) const
|
|
{
|
|
if (!pArgs)
|
|
return nullptr;
|
|
return pArgs->GetItem<T>(nSlotId, false);
|
|
}
|
|
template<class T> const T* GetArg(TypedWhichId<T> nSlotId) const
|
|
{
|
|
if (!pArgs)
|
|
return nullptr;
|
|
return pArgs->GetItem(nSlotId, false);
|
|
}
|
|
|
|
void ReleaseArgs();
|
|
void SetReturnValue(const SfxPoolItem &);
|
|
const SfxPoolItemHolder& GetReturnValue() const;
|
|
|
|
static css::uno::Reference< css::frame::XDispatchRecorder > GetMacroRecorder(const SfxViewFrame& rFrame);
|
|
static bool HasMacroRecorder(const SfxViewFrame& rFrame);
|
|
SfxCallMode GetCallMode() const;
|
|
void AllowRecording( bool );
|
|
bool AllowsRecording() const;
|
|
bool IsAPI() const;
|
|
bool IsSynchronCall() const;
|
|
void SetSynchronCall( bool bSynchron );
|
|
|
|
bool IsDone() const;
|
|
void Done( bool bRemove = false );
|
|
|
|
void Ignore();
|
|
void Cancel();
|
|
bool IsCancelled() const;
|
|
void Done(const SfxItemSet &);
|
|
|
|
void ForgetAllArgs();
|
|
|
|
/** Return the window that should be used as the parent for any dialogs this request creates
|
|
*/
|
|
weld::Window* GetFrameWeld() const;
|
|
|
|
void SetLokViewId(int nId);
|
|
|
|
int GetLokViewId() const;
|
|
|
|
private:
|
|
const SfxRequest& operator=(const SfxRequest &) = delete;
|
|
};
|
|
|
|
#endif
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|