/*
 * Copyright (C) 2008, 2009, 2010, 2012, 2014 Apple Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#if PLATFORM(IOS_FAMILY)

#import "WebGeolocationProviderIOS.h"

#import "WebDelegateImplementationCaching.h"
#import "WebGeolocationCoreLocationProvider.h"
#import <WebGeolocationPosition.h>
#import <WebUIDelegatePrivate.h>
#import <WebCore/GeolocationPosition.h>
#import <WebCore/WebCoreThread.h>
#import <WebCore/WebCoreThreadRun.h>
#import <wtf/HashSet.h>
#import <wtf/HashMap.h>
#import <wtf/RetainPtr.h>
#import <wtf/RunLoop.h>
#import <wtf/Vector.h>

using namespace WebCore;

@interface WebGeolocationPosition (Internal)
- (id)initWithGeolocationPosition:(GeolocationPositionData&&)coreGeolocationPosition;
@end

// CoreLocation runs in the main thread. WebGeolocationProviderIOS lives on the WebThread.
// _WebCoreLocationUpdateThreadingProxy forward updates from CoreLocation to WebGeolocationProviderIOS.
@interface _WebCoreLocationUpdateThreadingProxy : NSObject<WebGeolocationCoreLocationUpdateListener>
- (id)initWithProvider:(WebGeolocationProviderIOS*)provider;
@end

typedef HashMap<RetainPtr<WebView>, RetainPtr<id<WebGeolocationProviderInitializationListener> > > GeolocationInitializationCallbackMap;

@implementation WebGeolocationProviderIOS {
@private
    RetainPtr<WebGeolocationCoreLocationProvider> _coreLocationProvider;
    RetainPtr<_WebCoreLocationUpdateThreadingProxy> _coreLocationUpdateListenerProxy;

    BOOL _enableHighAccuracy;
    BOOL _isSuspended;
    BOOL _shouldResetOnResume;

    // WebViews waiting for CoreLocation to be ready. If the Application does not yet have the permission to use Geolocation
    // we also have to wait for that to be granted.
    GeolocationInitializationCallbackMap _webViewsWaitingForCoreLocationAuthorization;

    // List of WebView needing the initial position after registerWebView:. This is needed because WebKit does not
    // handle sending the position synchronously in response to registerWebView:, so we queue sending lastPosition behind a timer.
    HashSet<WebView*> _pendingInitialPositionWebView;

    // List of WebViews registered to WebGeolocationProvider for Geolocation update.
    HashSet<WebView*> _registeredWebViews;

    // All the views that might need a reset if the permission change externally.
    HashSet<WebView*> _trackedWebViews;

    RetainPtr<NSTimer> _sendLastPositionAsynchronouslyTimer;
    RetainPtr<WebGeolocationPosition> _lastPosition;
}

static inline void abortSendLastPosition(WebGeolocationProviderIOS* provider)
{
    provider->_pendingInitialPositionWebView.clear();
    [provider->_sendLastPositionAsynchronouslyTimer.get() invalidate];
    provider->_sendLastPositionAsynchronouslyTimer.clear();
}

- (void)dealloc
{
    abortSendLastPosition(self);
    [super dealloc];
}

#pragma mark - Public API of WebGeolocationProviderIOS.
+ (WebGeolocationProviderIOS *)sharedGeolocationProvider
{
    static dispatch_once_t once;
    static NeverDestroyed<RetainPtr<WebGeolocationProviderIOS>> sharedGeolocationProvider;
    dispatch_once(&once, ^{
        sharedGeolocationProvider.get() = adoptNS([[WebGeolocationProviderIOS alloc] init]);
    });
    return sharedGeolocationProvider.get().get();
}

- (void)suspend
{
    ASSERT(WebThreadIsLockedOrDisabled());
    ASSERT(pthread_main_np());

    ASSERT(!_isSuspended);
    _isSuspended = YES;

    // A new position is acquired and sent to all registered views on resume.
    _lastPosition.clear();
    abortSendLastPosition(self);
    [_coreLocationProvider stop];
}

- (void)resume
{
    ASSERT(WebThreadIsLockedOrDisabled());
    ASSERT(pthread_main_np());

    ASSERT(_isSuspended);
    _isSuspended = NO;

    if (_shouldResetOnResume) {
        [self resetGeolocation];
        _shouldResetOnResume = NO;
        return;
    }

    if (_registeredWebViews.isEmpty() && _webViewsWaitingForCoreLocationAuthorization.isEmpty())
        return;

    if (!_coreLocationProvider) {
        ASSERT(!_coreLocationUpdateListenerProxy);
        _coreLocationUpdateListenerProxy = adoptNS([[_WebCoreLocationUpdateThreadingProxy alloc] initWithProvider:self]);
        _coreLocationProvider = adoptNS([[WebGeolocationCoreLocationProvider alloc] initWithListener:_coreLocationUpdateListenerProxy.get()]);
    }

    if (!_webViewsWaitingForCoreLocationAuthorization.isEmpty())
        [_coreLocationProvider requestGeolocationAuthorization];

    if (!_registeredWebViews.isEmpty()) {
        [_coreLocationProvider setEnableHighAccuracy:_enableHighAccuracy];
        [_coreLocationProvider start];
    }
}

#pragma mark - Internal utility methods

- (void)_handlePendingInitialPosition:(NSTimer*)timer
{
    ASSERT_UNUSED(timer, timer == _sendLastPositionAsynchronouslyTimer);
    ASSERT(WebThreadIsCurrent());

    if (_lastPosition) {
        for (auto& webView : copyToVector(_pendingInitialPositionWebView))
            [webView _geolocationDidChangePosition:_lastPosition.get()];
    }
    abortSendLastPosition(self);
}

#pragma mark - Implementation of WebGeolocationProvider

- (void)registerWebView:(WebView *)webView
{
    ASSERT(WebThreadIsLockedOrDisabled());

    if (_registeredWebViews.contains(webView))
        return;

    _registeredWebViews.add(webView);
    if (!CallUIDelegateReturningBoolean(YES, webView, @selector(webViewCanCheckGeolocationAuthorizationStatus:)))
        return;

    if (!_isSuspended) {
        RunLoop::main().dispatch([self, strongSelf = retainPtr(self)] {
            if (!_coreLocationProvider) {
                ASSERT(!_coreLocationUpdateListenerProxy);
                _coreLocationUpdateListenerProxy = adoptNS([[_WebCoreLocationUpdateThreadingProxy alloc] initWithProvider:self]);
                _coreLocationProvider = adoptNS([[WebGeolocationCoreLocationProvider alloc] initWithListener:_coreLocationUpdateListenerProxy.get()]);
            }
            [_coreLocationProvider start];
        });
    }

    // We send the lastPosition asynchronously because WebKit does not handle updating the position synchronously.
    // On WebKit2, we could skip that and send the position directly from the UIProcess.
    _pendingInitialPositionWebView.add(webView);
    if (!_sendLastPositionAsynchronouslyTimer) {
        _sendLastPositionAsynchronouslyTimer = [NSTimer timerWithTimeInterval:0 target:self selector:@selector(_handlePendingInitialPosition:) userInfo:nil repeats:NO];
        [WebThreadNSRunLoop() addTimer:_sendLastPositionAsynchronouslyTimer.get() forMode:NSDefaultRunLoopMode];
    }
}

- (void)unregisterWebView:(WebView *)webView
{
    ASSERT(WebThreadIsLockedOrDisabled());

    if (!_registeredWebViews.contains(webView))
        return;

    _registeredWebViews.remove(webView);
    _pendingInitialPositionWebView.remove(webView);

    if (_registeredWebViews.isEmpty()) {
        RunLoop::main().dispatch([self, strongSelf = retainPtr(self)] {
            [_coreLocationProvider stop];
        });
        _enableHighAccuracy = NO;
        _lastPosition.clear();
    }
}

- (WebGeolocationPosition *)lastPosition
{
    ASSERT(WebThreadIsLockedOrDisabled());
    return _lastPosition.get();
}

- (void)setEnableHighAccuracy:(BOOL)enableHighAccuracy
{
    ASSERT(WebThreadIsLockedOrDisabled());
    _enableHighAccuracy = _enableHighAccuracy || enableHighAccuracy;
    RunLoop::main().dispatch([self, strongSelf = retainPtr(self)] {
        [_coreLocationProvider setEnableHighAccuracy:_enableHighAccuracy];
    });
}

- (void)initializeGeolocationForWebView:(WebView *)webView listener:(id<WebGeolocationProviderInitializationListener>)listener
{
    ASSERT(WebThreadIsLockedOrDisabled());

    if (!CallUIDelegateReturningBoolean(YES, webView, @selector(webViewCanCheckGeolocationAuthorizationStatus:)))
        return;

    _webViewsWaitingForCoreLocationAuthorization.add(webView, listener);
    _trackedWebViews.add(webView);

    RunLoop::main().dispatch([self, strongSelf = retainPtr(self)] {
        if (!_coreLocationProvider) {
            ASSERT(!_coreLocationUpdateListenerProxy);
            _coreLocationUpdateListenerProxy = adoptNS([[_WebCoreLocationUpdateThreadingProxy alloc] initWithProvider:self]);
            _coreLocationProvider = adoptNS([[WebGeolocationCoreLocationProvider alloc] initWithListener:_coreLocationUpdateListenerProxy.get()]);
        }
        [_coreLocationProvider requestGeolocationAuthorization];
    });
}

- (void)geolocationAuthorizationGranted
{
    ASSERT(WebThreadIsCurrent());

    GeolocationInitializationCallbackMap requests;
    requests.swap(_webViewsWaitingForCoreLocationAuthorization);

    for (const auto& slot : requests)
        [slot.value initializationAllowedWebView:slot.key.get()];
}

- (void)geolocationAuthorizationDenied
{
    ASSERT(WebThreadIsCurrent());

    GeolocationInitializationCallbackMap requests;
    requests.swap(_webViewsWaitingForCoreLocationAuthorization);

    for (const auto& slot : requests)
        [slot.value initializationDeniedWebView:slot.key.get()];
}

- (void)stopTrackingWebView:(WebView*)webView
{
    ASSERT(WebThreadIsLockedOrDisabled());
    _trackedWebViews.remove(webView);
}

#pragma mark - Mirror to WebGeolocationCoreLocationUpdateListener called by the proxy.

- (void)positionChanged:(WebGeolocationPosition*)position
{
    ASSERT(WebThreadIsCurrent());

    abortSendLastPosition(self);

    _lastPosition = position;
    for (auto& webView : copyToVector(_registeredWebViews))
        [webView _geolocationDidChangePosition:_lastPosition.get()];
}

- (void)errorOccurred:(NSString *)errorMessage
{
    ASSERT(WebThreadIsCurrent());

    _lastPosition.clear();

    for (auto& webView : copyToVector(_registeredWebViews))
        [webView _geolocationDidFailWithMessage:errorMessage];
}

- (void)resetGeolocation
{
    ASSERT(WebThreadIsCurrent());

    if (_isSuspended) {
        _shouldResetOnResume = YES;
        return;
    }
    // 1) Stop all ongoing Geolocation initialization and tracking.
    _webViewsWaitingForCoreLocationAuthorization.clear();
    _registeredWebViews.clear();
    abortSendLastPosition(self);

    // 2) Reset the views, each frame will register back if needed.
    for (auto& webView : copyToVector(_trackedWebViews))
        [webView _resetAllGeolocationPermission];
}
@end

#pragma mark - _WebCoreLocationUpdateThreadingProxy implementation.
@implementation _WebCoreLocationUpdateThreadingProxy {
    WebGeolocationProviderIOS* _provider;
}

- (id)initWithProvider:(WebGeolocationProviderIOS*)provider
{
    self = [super init];
    if (self)
        _provider = provider;
    return self;
}

- (void)geolocationAuthorizationGranted
{
    WebThreadRun(^{
        [_provider geolocationAuthorizationGranted];
    });
}

- (void)geolocationAuthorizationDenied
{
    WebThreadRun(^{
        [_provider geolocationAuthorizationDenied];
    });
}

- (void)positionChanged:(WebCore::GeolocationPositionData&&)position
{
    RetainPtr<WebGeolocationPosition> webPosition = adoptNS([[WebGeolocationPosition alloc] initWithGeolocationPosition:WTFMove(position)]);
    WebThreadRun(^{
        [_provider positionChanged:webPosition.get()];
    });
}

- (void)errorOccurred:(NSString *)errorMessage
{
    WebThreadRun(^{
        [_provider errorOccurred:errorMessage];
    });
}

- (void)resetGeolocation
{
    WebThreadRun(^{
        [_provider resetGeolocation];
    });
}
@end

#endif // PLATFORM(IOS_FAMILY)
