Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/ucb/source/ucp/tdoc/tdoc_docmgr.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
21
#include <rtl/ref.hxx>
22
#include <comphelper/diagnose_ex.hxx>
23
#include <sal/log.hxx>
24
#include <tools/datetime.hxx>
25
26
#include <comphelper/documentinfo.hxx>
27
#include <comphelper/namedvaluecollection.hxx>
28
#include <comphelper/sequence.hxx>
29
30
#include <com/sun/star/awt/XTopWindow.hpp>
31
#include <com/sun/star/beans/XPropertySet.hpp>
32
#include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
33
#include <com/sun/star/document/XStorageBasedDocument.hpp>
34
#include <com/sun/star/frame/UnknownModuleException.hpp>
35
#include <com/sun/star/frame/theGlobalEventBroadcaster.hpp>
36
#include <com/sun/star/frame/ModuleManager.hpp>
37
#include <com/sun/star/lang/DisposedException.hpp>
38
#include <com/sun/star/lang/NotInitializedException.hpp>
39
#include <com/sun/star/util/XCloseBroadcaster.hpp>
40
41
#include "tdoc_docmgr.hxx"
42
#include "tdoc_provider.hxx"
43
44
using namespace com::sun::star;
45
using namespace tdoc_ucp;
46
47
// OfficeDocumentsCloseListener Implementation.
48
49
50
// util::XCloseListener
51
52
53
// virtual
54
void SAL_CALL OfficeDocumentsManager::OfficeDocumentsCloseListener::queryClosing(
55
         const lang::EventObject& /*Source*/, sal_Bool /*GetsOwnership*/ )
56
0
{
57
0
}
58
59
60
void SAL_CALL OfficeDocumentsManager::OfficeDocumentsCloseListener::notifyClosing(
61
         const lang::EventObject& Source )
62
0
{
63
0
    if (!m_pManager) return; // disposed?
64
65
0
    document::DocumentEvent aDocEvent;
66
0
    aDocEvent.Source = Source.Source;
67
0
    aDocEvent.EventName = "OfficeDocumentsListener::notifyClosing";
68
0
    m_pManager->documentEventOccured( aDocEvent );
69
0
}
70
71
72
// lang::XDocumentEventListener (base of util::XCloseListener)
73
74
75
// virtual
76
void SAL_CALL OfficeDocumentsManager::OfficeDocumentsCloseListener::disposing(
77
        const lang::EventObject& /*Source*/ )
78
0
{
79
0
}
80
81
82
// OfficeDocumentsManager Implementation.
83
84
85
OfficeDocumentsManager::OfficeDocumentsManager(
86
            const uno::Reference< uno::XComponentContext > & rxContext,
87
            ContentProvider * pDocEventListener )
88
9.09k
: m_xContext( rxContext ),
89
9.09k
  m_xDocEvtNotifier( frame::theGlobalEventBroadcaster::get( rxContext ) ),
90
9.09k
  m_pDocEventListener( pDocEventListener ),
91
9.09k
  m_xDocCloseListener( new OfficeDocumentsCloseListener( this ) )
92
9.09k
{
93
    // Order is important (multithreaded environment)
94
9.09k
    uno::Reference< document::XDocumentEventBroadcaster >(
95
9.09k
        m_xDocEvtNotifier, uno::UNO_QUERY_THROW )->addDocumentEventListener( this );
96
9.09k
    buildDocumentsList();
97
9.09k
}
98
99
100
// virtual
101
OfficeDocumentsManager::~OfficeDocumentsManager()
102
9.09k
{
103
    //OSL_ENSURE( m_aDocs.empty(), "document list not empty!" );
104
    // no need to assert this: Normal shutdown of LibreOffice could already trigger it, since the order
105
    // in which objects are actually released/destroyed upon shutdown is not defined. And when we
106
    // arrive *here*, LibreOffice *is* shutting down currently, since we're held by the TDOC provider,
107
    // which is disposed upon shutdown.
108
9.09k
    m_xDocCloseListener->Dispose();
109
9.09k
}
110
111
112
void OfficeDocumentsManager::destroy()
113
9.09k
{
114
9.09k
    uno::Reference< document::XDocumentEventBroadcaster >(
115
9.09k
        m_xDocEvtNotifier, uno::UNO_QUERY_THROW )->removeDocumentEventListener( this );
116
9.09k
}
117
118
119
static OUString
120
getDocumentId( const uno::Reference< uno::XInterface > & xDoc )
121
9.09k
{
122
9.09k
    OUString aId;
123
124
    // Try to get the UID directly from the document.
125
9.09k
    uno::Reference< beans::XPropertySet > xPropSet( xDoc, uno::UNO_QUERY );
126
9.09k
    if ( xPropSet.is() )
127
9.09k
    {
128
9.09k
        try
129
9.09k
        {
130
9.09k
            uno::Any aValue = xPropSet->getPropertyValue(u"RuntimeUID"_ustr);
131
9.09k
            aValue >>= aId;
132
9.09k
        }
133
9.09k
        catch ( beans::UnknownPropertyException const & )
134
9.09k
        {
135
            // Not actually an error. Property is optional.
136
0
        }
137
9.09k
        catch ( lang::WrappedTargetException const & )
138
9.09k
        {
139
0
            TOOLS_WARN_EXCEPTION("ucb.ucp", "Caught WrappedTargetException!");
140
0
        }
141
9.09k
    }
142
143
9.09k
    if ( aId.isEmpty() )
144
0
    {
145
        // fallback: generate UID from document's this pointer.
146
        // normalize the interface pointer first. Else, calls with different
147
        // interfaces to the same object (say, XFoo and XBar) will produce
148
        // different IDs
149
0
        uno::Reference< uno::XInterface > xNormalizedIFace( xDoc, uno::UNO_QUERY );
150
0
        sal_Int64 nId = reinterpret_cast< sal_Int64 >( xNormalizedIFace.get() );
151
0
        aId = OUString::number( nId );
152
0
    }
153
154
9.09k
    OSL_ENSURE( !aId.isEmpty(), "getDocumentId - Empty id!" );
155
9.09k
    return aId;
156
9.09k
}
157
158
159
// document::XDocumentEventListener
160
161
162
// virtual
163
void SAL_CALL OfficeDocumentsManager::documentEventOccured(
164
        const document::DocumentEvent & Event )
165
0
{
166
/*
167
    Events documentation: OOo Developer's Guide / Writing UNO Components /
168
    Integrating Components into OpenOffice.org / Jobs
169
*/
170
171
0
    if ( Event.EventName == "OnLoadFinished" // document loaded
172
0
      || Event.EventName == "OnCreate" )     // document created
173
0
    {
174
0
        if ( isOfficeDocument( Event.Source ) )
175
0
        {
176
0
            uno::Reference<frame::XModel> const xModel(
177
0
                    Event.Source, uno::UNO_QUERY );
178
0
            OSL_ENSURE( xModel.is(), "Got no frame::XModel!" );
179
180
0
            bool found(false);
181
182
0
            {
183
0
                std::scoped_lock aGuard( m_aMtx );
184
185
0
                found = std::any_of(m_aDocs.begin(), m_aDocs.end(),
186
0
                    [&xModel](const DocumentList::value_type& rEntry) { return rEntry.second.xModel == xModel; });
187
0
            }
188
189
0
            if (!found)
190
0
            {
191
                // no mutex to avoid deadlocks!
192
                // need no lock to access const members, ContentProvider is safe
193
194
                // new document
195
196
0
                uno::Reference< document::XStorageBasedDocument >
197
0
                    xDoc( Event.Source, uno::UNO_QUERY );
198
0
                OSL_ENSURE( xDoc.is(), "Got no document::XStorageBasedDocument!" );
199
200
0
                uno::Reference< embed::XStorage > xStorage
201
0
                    = xDoc->getDocumentStorage();
202
0
                OSL_ENSURE( xStorage.is(), "Got no document storage!" );
203
204
0
                rtl:: OUString aDocId = getDocumentId( Event.Source );
205
0
                rtl:: OUString aTitle = comphelper::DocumentInfo::getDocumentTitle(
206
0
                    uno::Reference< frame::XModel >( Event.Source, uno::UNO_QUERY ) );
207
208
0
                {
209
0
                    std::scoped_lock g(m_aMtx);
210
0
                    m_aDocs[ aDocId ] = StorageInfo( aTitle, xStorage, xModel );
211
0
                }
212
213
0
                uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster(
214
0
                    Event.Source, uno::UNO_QUERY );
215
0
                OSL_ENSURE( xCloseBroadcaster.is(),
216
0
                    "OnLoadFinished/OnCreate event: got no close broadcaster!" );
217
218
0
                if ( xCloseBroadcaster.is() )
219
0
                    xCloseBroadcaster->addCloseListener(m_xDocCloseListener);
220
221
                // Propagate document closure.
222
0
                OSL_ENSURE( m_pDocEventListener,
223
0
                    "OnLoadFinished/OnCreate event: no owner for insert event propagation!" );
224
225
0
                if ( m_pDocEventListener )
226
0
                    m_pDocEventListener->notifyDocumentOpened( aDocId );
227
0
            }
228
0
        }
229
0
    }
230
0
    else if ( Event.EventName == "OfficeDocumentsListener::notifyClosing" )
231
0
    {
232
0
        if ( isOfficeDocument( Event.Source ) )
233
0
        {
234
            // Document has been closed (unloaded)
235
236
            // Official event "OnUnload" does not work here. Event
237
            // gets fired too early. Other OnUnload listeners called after this
238
            // listener may still need TDOC access to the document. Remove the
239
            // document from TDOC docs list on XCloseListener::notifyClosing.
240
            // See OfficeDocumentsManager::OfficeDocumentsListener::notifyClosing.
241
242
0
            uno::Reference< frame::XModel >
243
0
                 xModel( Event.Source, uno::UNO_QUERY );
244
0
            OSL_ENSURE( xModel.is(), "Got no frame::XModel!" );
245
246
0
            bool found(false);
247
0
            OUString aDocId;
248
249
0
            {
250
0
                std::scoped_lock aGuard( m_aMtx );
251
252
0
                auto it = std::find_if(m_aDocs.begin(), m_aDocs.end(),
253
0
                    [&xModel](const DocumentList::value_type& rEntry) { return rEntry.second.xModel == xModel; });
254
0
                if ( it != m_aDocs.end() )
255
0
                {
256
0
                    aDocId = (*it).first;
257
0
                    found = true;
258
0
                    m_aDocs.erase( it );
259
0
                }
260
0
            }
261
262
0
            OSL_ENSURE( found,
263
0
                        "OnUnload event notified for unknown document!" );
264
265
0
            if (found)
266
0
            {
267
                // Propagate document closure.
268
0
                OSL_ENSURE( m_pDocEventListener,
269
0
                    "OnUnload event: no owner for close event propagation!" );
270
0
                if (m_pDocEventListener)
271
0
                {
272
0
                    m_pDocEventListener->notifyDocumentClosed(aDocId);
273
0
                }
274
0
                uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster(
275
0
                    Event.Source, uno::UNO_QUERY );
276
0
                OSL_ENSURE( xCloseBroadcaster.is(),
277
0
                    "OnUnload event: got no XCloseBroadcaster from XModel" );
278
0
                if ( xCloseBroadcaster.is() )
279
0
                    xCloseBroadcaster->removeCloseListener(m_xDocCloseListener);
280
0
            }
281
0
        }
282
0
    }
283
0
    else if ( Event.EventName == "OnSaveDone" )
284
0
    {
285
0
        if ( isOfficeDocument( Event.Source ) )
286
0
        {
287
            // Storage gets exchanged while saving.
288
0
            uno::Reference<document::XStorageBasedDocument> const xDoc(
289
0
                    Event.Source, uno::UNO_QUERY );
290
0
            OSL_ENSURE( xDoc.is(),
291
0
                        "Got no document::XStorageBasedDocument!" );
292
0
            uno::Reference<embed::XStorage> const xStorage(
293
0
                xDoc->getDocumentStorage());
294
0
            OSL_ENSURE( xStorage.is(), "Got no document storage!" );
295
296
0
            uno::Reference< frame::XModel >
297
0
                 xModel( Event.Source, uno::UNO_QUERY );
298
0
            OSL_ENSURE( xModel.is(), "Got no frame::XModel!" );
299
300
0
            std::scoped_lock aGuard( m_aMtx );
301
302
0
            DocumentList::iterator it = std::find_if(m_aDocs.begin(), m_aDocs.end(),
303
0
                [&xModel](const DocumentList::value_type& rEntry) { return rEntry.second.xModel == xModel; });
304
305
0
            OSL_ENSURE( it != m_aDocs.end(),
306
0
                        "OnSaveDone event notified for unknown document!" );
307
0
            if ( it != m_aDocs.end() )
308
0
            {
309
0
                (*it).second.xStorage = xStorage;
310
0
            }
311
0
        }
312
0
    }
313
0
    else if ( Event.EventName == "OnSaveAsDone" )
314
0
    {
315
0
        if ( isOfficeDocument( Event.Source ) )
316
0
        {
317
            // Storage gets exchanged while saving.
318
0
            uno::Reference<document::XStorageBasedDocument> const xDoc(
319
0
                    Event.Source, uno::UNO_QUERY );
320
0
            OSL_ENSURE( xDoc.is(),
321
0
                        "Got no document::XStorageBasedDocument!" );
322
0
            uno::Reference<embed::XStorage> const xStorage(
323
0
                xDoc->getDocumentStorage());
324
0
            OSL_ENSURE( xStorage.is(), "Got no document storage!" );
325
326
0
            uno::Reference< frame::XModel >
327
0
                 xModel( Event.Source, uno::UNO_QUERY );
328
0
            OSL_ENSURE( xModel.is(), "Got no frame::XModel!" );
329
330
0
            OUString const title(comphelper::DocumentInfo::getDocumentTitle(xModel));
331
332
0
            std::scoped_lock aGuard( m_aMtx );
333
334
0
            DocumentList::iterator it = std::find_if(m_aDocs.begin(), m_aDocs.end(),
335
0
                [&xModel](const DocumentList::value_type& rEntry) { return rEntry.second.xModel == xModel; });
336
337
0
            OSL_ENSURE( it != m_aDocs.end(),
338
0
                        "OnSaveAsDone event notified for unknown document!" );
339
0
            if ( it != m_aDocs.end() )
340
0
            {
341
0
                (*it).second.xStorage = xStorage;
342
343
                // Adjust title.
344
0
                (*it).second.aTitle = title;
345
0
            }
346
0
        }
347
0
    }
348
0
    else if ( Event.EventName == "OnTitleChanged"
349
0
           || Event.EventName == "OnStorageChanged" )
350
0
    {
351
0
        if ( isOfficeDocument( Event.Source ) )
352
0
        {
353
            // Storage gets exchanged while saving.
354
0
            uno::Reference<document::XStorageBasedDocument> const xDoc(
355
0
                    Event.Source, uno::UNO_QUERY );
356
0
            OSL_ENSURE( xDoc.is(),
357
0
                        "Got no document::XStorageBasedDocument!" );
358
0
            uno::Reference<embed::XStorage> const xStorage(
359
0
                xDoc->getDocumentStorage());
360
0
            OSL_ENSURE( xStorage.is(), "Got no document storage!" );
361
362
0
            uno::Reference< frame::XModel >
363
0
                 xModel( Event.Source, uno::UNO_QUERY );
364
0
            OSL_ENSURE( xModel.is(), "Got no frame::XModel!" );
365
366
0
            OUString const aTitle(comphelper::DocumentInfo::getDocumentTitle(xModel));
367
368
0
            OUString const aDocId(getDocumentId(Event.Source));
369
370
0
            std::scoped_lock aGuard( m_aMtx );
371
372
0
            DocumentList::iterator it = std::find_if(m_aDocs.begin(), m_aDocs.end(),
373
0
                [&xModel](const DocumentList::value_type& rEntry) { return rEntry.second.xModel == xModel; });
374
0
            if ( it != m_aDocs.end() )
375
0
            {
376
                // Adjust title.
377
0
                (*it).second.aTitle = aTitle;
378
379
0
                m_aDocs[ aDocId ] = StorageInfo( aTitle, xStorage, xModel );
380
0
            }
381
382
//            OSL_ENSURE( it != m_aDocs.end(),
383
//                        "TitleChanged event notified for unknown document!" );
384
            // TODO: re-enable this assertion. It has been disabled for now, since it breaks the assertion-free smoketest,
385
            // and the fix is more difficult than what can be done now.
386
            // The problem is that at the moment, when you close a SFX-based document via API, it will first
387
            // fire the notifyClosing event, which will make the OfficeDocumentsManager remove the doc from its list.
388
            // Then, it will notify an OnTitleChanged, then an OnUnload. Documents closed via call the notifyClosing
389
            // *after* OnUnload and all other On* events.
390
            // In agreement with MBA, the implementation for SfxBaseModel::Close should be changed to also send notifyClosing
391
            // as last event. When this happens, the assertion here must be enabled, again.
392
0
        }
393
0
    }
394
0
}
395
396
// lang::XDocumentEventListener (base of document::XDocumentEventListener)
397
398
// virtual
399
void SAL_CALL OfficeDocumentsManager::disposing(
400
        const lang::EventObject& /*Source*/ )
401
0
{
402
0
}
403
404
// Non-interface.
405
406
void OfficeDocumentsManager::buildDocumentsList()
407
9.09k
{
408
9.09k
    uno::Reference< container::XEnumeration > xEnum
409
9.09k
        = m_xDocEvtNotifier->createEnumeration();
410
411
9.09k
    while ( xEnum->hasMoreElements() )
412
0
    {
413
0
        uno::Any aValue = xEnum->nextElement();
414
        // container::NoSuchElementException
415
        // lang::WrappedTargetException
416
417
0
        try
418
0
        {
419
0
            uno::Reference< frame::XModel > xModel;
420
0
            aValue >>= xModel;
421
422
0
            if ( xModel.is() )
423
0
            {
424
0
                if ( isOfficeDocument( xModel ) )
425
0
                {
426
0
                    bool found(false);
427
428
0
                    {
429
0
                        std::scoped_lock aGuard( m_aMtx );
430
431
0
                        found = std::any_of(m_aDocs.begin(), m_aDocs.end(),
432
0
                            [&xModel](const DocumentList::value_type& rEntry) { return rEntry.second.xModel == xModel; });
433
0
                    }
434
435
0
                    if (!found)
436
0
                    {
437
                        // new document
438
0
                        OUString aDocId = getDocumentId( xModel );
439
0
                        OUString aTitle = comphelper::DocumentInfo::getDocumentTitle( xModel );
440
441
0
                        uno::Reference< document::XStorageBasedDocument >
442
0
                                xDoc( xModel, uno::UNO_QUERY );
443
0
                        OSL_ENSURE( xDoc.is(),
444
0
                            "Got no document::XStorageBasedDocument!" );
445
446
0
                        uno::Reference< embed::XStorage > xStorage
447
0
                            = xDoc->getDocumentStorage();
448
0
                        OSL_ENSURE( xStorage.is(), "Got no document storage!" );
449
450
0
                        {
451
0
                            std::scoped_lock aGuard( m_aMtx );
452
0
                            m_aDocs[ aDocId ]
453
0
                                = StorageInfo( aTitle, xStorage, xModel );
454
0
                        }
455
456
0
                        uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster(
457
0
                            xModel, uno::UNO_QUERY );
458
0
                        OSL_ENSURE( xCloseBroadcaster.is(),
459
0
                            "buildDocumentsList: got no close broadcaster!" );
460
461
0
                        if ( xCloseBroadcaster.is() )
462
0
                            xCloseBroadcaster->addCloseListener(m_xDocCloseListener);
463
0
                    }
464
0
                }
465
0
            }
466
0
        }
467
0
        catch ( lang::DisposedException const & )
468
0
        {
469
            // Note: Due to race conditions the XEnumeration can
470
            //       contain docs that have already been closed
471
0
        }
472
0
        catch ( lang::NotInitializedException const & )
473
0
        {
474
            // Note: Due to race conditions the XEnumeration can
475
            //       contain docs that are still uninitialized
476
0
        }
477
0
    }
478
9.09k
}
479
480
uno::Reference< embed::XStorage >
481
OfficeDocumentsManager::queryStorage( const OUString & rDocId )
482
3.05k
{
483
3.05k
    std::scoped_lock aGuard( m_aMtx );
484
485
3.05k
    DocumentList::const_iterator it = m_aDocs.find( rDocId );
486
3.05k
    if ( it == m_aDocs.end() )
487
3.05k
        return uno::Reference< embed::XStorage >();
488
489
0
    return (*it).second.xStorage;
490
3.05k
}
491
492
493
OUString OfficeDocumentsManager::queryDocumentId(
494
    const uno::Reference< frame::XModel > & xModel )
495
9.09k
{
496
9.09k
    return getDocumentId( xModel );
497
9.09k
}
498
499
500
uno::Reference< frame::XModel >
501
OfficeDocumentsManager::queryDocumentModel( const OUString & rDocId )
502
0
{
503
0
    std::scoped_lock aGuard( m_aMtx );
504
505
0
    DocumentList::const_iterator it = m_aDocs.find( rDocId );
506
0
    if ( it == m_aDocs.end() )
507
0
        return uno::Reference< frame::XModel >();
508
509
0
    return (*it).second.xModel;
510
0
}
511
512
513
uno::Sequence< OUString > OfficeDocumentsManager::queryDocuments()
514
0
{
515
0
    std::scoped_lock aGuard( m_aMtx );
516
517
0
    return comphelper::mapKeysToSequence( m_aDocs );
518
0
}
519
520
521
OUString
522
OfficeDocumentsManager::queryStorageTitle( const OUString & rDocId )
523
0
{
524
0
    std::scoped_lock aGuard( m_aMtx );
525
526
0
    DocumentList::const_iterator it = m_aDocs.find( rDocId );
527
0
    if ( it == m_aDocs.end() )
528
0
        return OUString();
529
530
0
    return (*it).second.aTitle;
531
0
}
532
533
534
0
css::util::DateTime OfficeDocumentsManager::queryStreamDateModified(OUString const & uri) {
535
0
    std::scoped_lock g(m_aMtx);
536
0
    auto const i1 = m_aDocs.find(Uri(uri).getDocumentId());
537
0
    if (i1 != m_aDocs.end()) {
538
0
        auto const i2 = i1->second.streamDateModified.find(uri);
539
0
        if (i2 != i1->second.streamDateModified.end()) {
540
0
            return i2->second;
541
0
        }
542
0
    }
543
0
    return {};
544
0
}
545
546
547
0
void OfficeDocumentsManager::updateStreamDateModified(OUString const & uri) {
548
0
    std::scoped_lock g(m_aMtx);
549
0
    auto const i = m_aDocs.find(Uri(uri).getDocumentId());
550
0
    if (i == m_aDocs.end()) {
551
0
        SAL_WARN("ucb.ucp.tdoc", "No document info for <" << uri << ">");
552
0
        return;
553
0
    }
554
0
    i->second.streamDateModified[uri] = DateTime(DateTime::SYSTEM).GetUNODateTime();
555
0
}
556
557
558
bool OfficeDocumentsManager::isDocumentPreview(
559
        const uno::Reference< frame::XModel3 > & xModel )
560
0
{
561
0
    if ( !xModel.is() )
562
0
        return false;
563
564
0
    uno::Sequence<beans::PropertyValue> props = xModel->getArgs2( { u"Preview"_ustr } );
565
0
    for (const auto & rProp : props)
566
0
        if (rProp.Name == "Preview")
567
0
        {
568
0
            bool bIsPreview = false;
569
0
            rProp.Value >>= bIsPreview;
570
0
            return bIsPreview;
571
0
        }
572
0
    return false;
573
0
}
574
575
576
bool OfficeDocumentsManager::isHelpDocument(
577
        const uno::Reference< frame::XModel > & xModel )
578
0
{
579
0
    if ( !xModel.is() )
580
0
        return false;
581
582
0
    OUString sURL( xModel->getURL() );
583
0
    return sURL.match( "vnd.sun.star.help://" );
584
0
}
585
586
587
bool OfficeDocumentsManager::isWithoutOrInTopLevelFrame(
588
        const uno::Reference< frame::XModel > & xModel )
589
0
{
590
0
    if ( !xModel.is() )
591
0
        return false;
592
593
0
    uno::Reference< frame::XController > xController
594
0
        = xModel->getCurrentController();
595
0
    if ( xController.is() )
596
0
    {
597
0
        uno::Reference< frame::XFrame > xFrame
598
0
            = xController->getFrame();
599
0
        if ( xFrame.is() )
600
0
        {
601
            // don't use XFrame::isTop here. This nowadays excludes
602
            // "sub documents" such as forms embedded in database documents
603
0
            uno::Reference< awt::XTopWindow > xFrameContainer(
604
0
                xFrame->getContainerWindow(), uno::UNO_QUERY );
605
0
            if ( !xFrameContainer.is() )
606
0
                return false;
607
0
        }
608
0
    }
609
610
0
    return true;
611
0
}
612
613
614
bool OfficeDocumentsManager::isBasicIDE(
615
        const uno::Reference< frame::XModel > & xModel )
616
0
{
617
0
    if ( !m_xModuleMgr.is() )
618
0
    {
619
0
        std::scoped_lock aGuard( m_aMtx );
620
0
        if ( !m_xModuleMgr.is() )
621
0
        {
622
0
            try
623
0
            {
624
0
                m_xModuleMgr = frame::ModuleManager::create( m_xContext );
625
0
            }
626
0
            catch ( uno::Exception const & )
627
0
            {
628
                // handled below.
629
0
            }
630
631
0
            OSL_ENSURE( m_xModuleMgr .is(),
632
0
                        "Could not instantiate ModuleManager service!" );
633
0
        }
634
0
    }
635
636
0
    if ( m_xModuleMgr.is() )
637
0
    {
638
0
        OUString aModule;
639
0
        try
640
0
        {
641
0
            aModule = m_xModuleMgr->identify( xModel );
642
0
        }
643
0
        catch ( lang::IllegalArgumentException const & )
644
0
        {
645
0
            TOOLS_WARN_EXCEPTION("ucb.ucp", "");
646
0
        }
647
0
        catch ( frame::UnknownModuleException const & )
648
0
        {
649
0
            TOOLS_WARN_EXCEPTION("ucb.ucp", "");
650
0
        }
651
652
0
        if ( !aModule.isEmpty() )
653
0
        {
654
            // Filter unwanted items, that are no real documents.
655
0
            if ( aModule == "com.sun.star.script.BasicIDE" )
656
0
            {
657
0
                return true;
658
0
            }
659
0
        }
660
0
    }
661
662
0
    return false;
663
0
}
664
665
666
bool OfficeDocumentsManager::isOfficeDocument(
667
        const uno::Reference< uno::XInterface > & xDoc )
668
0
{
669
0
    uno::Reference< frame::XModel > xModel( xDoc, uno::UNO_QUERY );
670
0
    uno::Reference< document::XStorageBasedDocument >
671
0
        xStorageBasedDoc( xModel, uno::UNO_QUERY );
672
0
    if ( !xStorageBasedDoc.is() )
673
0
        return false;
674
0
    uno::Reference< frame::XModel3 > xModel3( xDoc, uno::UNO_QUERY );
675
0
    assert(xModel3 && "anything implementing frame:XModel is expected to implement XModel3 as well");
676
677
0
    if ( !isWithoutOrInTopLevelFrame( xModel ) )
678
0
        return false;
679
680
0
    if ( isDocumentPreview( xModel3 ) )
681
0
        return false;
682
683
0
    if ( isHelpDocument( xModel ) )
684
0
        return false;
685
686
0
    if ( isBasicIDE( xModel ) )
687
0
        return false;
688
689
0
    return true;
690
0
}
691
692
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */