Issue #1751 -- Remove cocoa support code from /dom

This commit is contained in:
Moonchild 2021-05-08 20:59:55 +00:00 committed by roytam1
commit a6ae35ba91
23 changed files with 1 additions and 2293 deletions

View file

@ -1,590 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
// mostly derived from the Allegro source code at:
// http://alleg.svn.sourceforge.net/viewvc/alleg/allegro/branches/4.9/src/macosx/hidjoy.m?revision=13760&view=markup
#include "mozilla/dom/Gamepad.h"
#include "mozilla/dom/GamepadPlatformService.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Unused.h"
#include "nsThreadUtils.h"
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/hid/IOHIDBase.h>
#include <IOKit/hid/IOHIDKeys.h>
#include <IOKit/hid/IOHIDManager.h>
#include <stdio.h>
#include <vector>
namespace {
using namespace mozilla;
using namespace mozilla::dom;
using std::vector;
struct Button {
int id;
bool analog;
IOHIDElementRef element;
CFIndex min;
CFIndex max;
Button(int aId, IOHIDElementRef aElement, CFIndex aMin, CFIndex aMax) :
id(aId),
analog((aMax - aMin) > 1),
element(aElement),
min(aMin),
max(aMax) {}
};
struct Axis {
int id;
IOHIDElementRef element;
uint32_t usagePage;
uint32_t usage;
CFIndex min;
CFIndex max;
};
typedef bool dpad_buttons[4];
// These values can be found in the USB HID Usage Tables:
// http://www.usb.org/developers/hidpage
const unsigned kDesktopUsagePage = 0x01;
const unsigned kSimUsagePage = 0x02;
const unsigned kAcceleratorUsage = 0xC4;
const unsigned kBrakeUsage = 0xC5;
const unsigned kJoystickUsage = 0x04;
const unsigned kGamepadUsage = 0x05;
const unsigned kAxisUsageMin = 0x30;
const unsigned kAxisUsageMax = 0x35;
const unsigned kDpadUsage = 0x39;
const unsigned kButtonUsagePage = 0x09;
const unsigned kConsumerPage = 0x0C;
const unsigned kHomeUsage = 0x223;
const unsigned kBackUsage = 0x224;
class Gamepad {
private:
IOHIDDeviceRef mDevice;
nsTArray<Button> buttons;
nsTArray<Axis> axes;
IOHIDElementRef mDpad;
dpad_buttons mDpadState;
public:
Gamepad() : mDevice(nullptr), mDpad(nullptr), mSuperIndex(-1) {}
bool operator==(IOHIDDeviceRef device) const { return mDevice == device; }
bool empty() const { return mDevice == nullptr; }
void clear()
{
mDevice = nullptr;
buttons.Clear();
axes.Clear();
mDpad = nullptr;
mSuperIndex = -1;
}
void init(IOHIDDeviceRef device);
size_t numButtons() { return buttons.Length() + (mDpad ? 4 : 0); }
size_t numAxes() { return axes.Length(); }
// Index given by our superclass.
uint32_t mSuperIndex;
bool isDpad(IOHIDElementRef element) const
{
return element == mDpad;
}
const dpad_buttons& getDpadState() const
{
return mDpadState;
}
void setDpadState(const dpad_buttons& dpadState)
{
for (unsigned i = 0; i < ArrayLength(mDpadState); i++) {
mDpadState[i] = dpadState[i];
}
}
const Button* lookupButton(IOHIDElementRef element) const
{
for (unsigned i = 0; i < buttons.Length(); i++) {
if (buttons[i].element == element)
return &buttons[i];
}
return nullptr;
}
const Axis* lookupAxis(IOHIDElementRef element) const
{
for (unsigned i = 0; i < axes.Length(); i++) {
if (axes[i].element == element)
return &axes[i];
}
return nullptr;
}
};
class AxisComparator {
public:
bool Equals(const Axis& a1, const Axis& a2) const
{
return a1.usagePage == a2.usagePage && a1.usage == a2.usage;
}
bool LessThan(const Axis& a1, const Axis& a2) const
{
if (a1.usagePage == a2.usagePage) {
return a1.usage < a2.usage;
}
return a1.usagePage < a2.usagePage;
}
};
void Gamepad::init(IOHIDDeviceRef device)
{
clear();
mDevice = device;
CFArrayRef elements = IOHIDDeviceCopyMatchingElements(device,
nullptr,
kIOHIDOptionsTypeNone);
CFIndex n = CFArrayGetCount(elements);
for (CFIndex i = 0; i < n; i++) {
IOHIDElementRef element = (IOHIDElementRef)CFArrayGetValueAtIndex(elements,
i);
uint32_t usagePage = IOHIDElementGetUsagePage(element);
uint32_t usage = IOHIDElementGetUsage(element);
if (usagePage == kDesktopUsagePage &&
usage >= kAxisUsageMin &&
usage <= kAxisUsageMax)
{
Axis axis = { int(axes.Length()),
element,
usagePage,
usage,
IOHIDElementGetLogicalMin(element),
IOHIDElementGetLogicalMax(element) };
axes.AppendElement(axis);
} else if (usagePage == kDesktopUsagePage && usage == kDpadUsage &&
// Don't know how to handle d-pads that return weird values.
IOHIDElementGetLogicalMax(element) - IOHIDElementGetLogicalMin(element) == 7) {
mDpad = element;
} else if ((usagePage == kSimUsagePage &&
(usage == kAcceleratorUsage ||
usage == kBrakeUsage)) ||
(usagePage == kButtonUsagePage) ||
(usagePage == kConsumerPage &&
(usage == kHomeUsage ||
usage == kBackUsage))) {
Button button(int(buttons.Length()), element, IOHIDElementGetLogicalMin(element), IOHIDElementGetLogicalMax(element));
buttons.AppendElement(button);
} else {
//TODO: handle other usage pages
}
}
AxisComparator comparator;
axes.Sort(comparator);
for (unsigned i = 0; i < axes.Length(); i++) {
axes[i].id = i;
}
}
class DarwinGamepadService {
private:
IOHIDManagerRef mManager;
vector<Gamepad> mGamepads;
//Workaround to support running in background thread
CFRunLoopRef mMonitorRunLoop;
nsCOMPtr<nsIThread> mMonitorThread;
static void DeviceAddedCallback(void* data, IOReturn result,
void* sender, IOHIDDeviceRef device);
static void DeviceRemovedCallback(void* data, IOReturn result,
void* sender, IOHIDDeviceRef device);
static void InputValueChangedCallback(void* data, IOReturn result,
void* sender, IOHIDValueRef newValue);
void DeviceAdded(IOHIDDeviceRef device);
void DeviceRemoved(IOHIDDeviceRef device);
void InputValueChanged(IOHIDValueRef value);
void StartupInternal();
public:
DarwinGamepadService();
~DarwinGamepadService();
void Startup();
void Shutdown();
friend class DarwinGamepadServiceStartupRunnable;
};
class DarwinGamepadServiceStartupRunnable final : public Runnable
{
private:
~DarwinGamepadServiceStartupRunnable() {}
// This Runnable schedules startup of DarwinGamepadService
// in a new thread, pointer to DarwinGamepadService is only
// used by this Runnable within its thread.
DarwinGamepadService MOZ_NON_OWNING_REF *mService;
public:
explicit DarwinGamepadServiceStartupRunnable(DarwinGamepadService *service)
: mService(service) {}
NS_IMETHOD Run() override
{
MOZ_ASSERT(mService);
mService->StartupInternal();
return NS_OK;
}
};
void
DarwinGamepadService::DeviceAdded(IOHIDDeviceRef device)
{
RefPtr<GamepadPlatformService> service =
GamepadPlatformService::GetParentService();
if (!service) {
return;
}
size_t slot = size_t(-1);
for (size_t i = 0; i < mGamepads.size(); i++) {
if (mGamepads[i] == device)
return;
if (slot == size_t(-1) && mGamepads[i].empty())
slot = i;
}
if (slot == size_t(-1)) {
slot = mGamepads.size();
mGamepads.push_back(Gamepad());
}
mGamepads[slot].init(device);
// Gather some identifying information
CFNumberRef vendorIdRef =
(CFNumberRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey));
CFNumberRef productIdRef =
(CFNumberRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey));
CFStringRef productRef =
(CFStringRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
int vendorId, productId;
CFNumberGetValue(vendorIdRef, kCFNumberIntType, &vendorId);
CFNumberGetValue(productIdRef, kCFNumberIntType, &productId);
char product_name[128];
CFStringGetCString(productRef, product_name,
sizeof(product_name), kCFStringEncodingASCII);
char buffer[256];
sprintf(buffer, "%x-%x-%s", vendorId, productId, product_name);
uint32_t index = service->AddGamepad(buffer,
mozilla::dom::GamepadMappingType::_empty,
(int)mGamepads[slot].numButtons(),
(int)mGamepads[slot].numAxes());
mGamepads[slot].mSuperIndex = index;
}
void
DarwinGamepadService::DeviceRemoved(IOHIDDeviceRef device)
{
RefPtr<GamepadPlatformService> service =
GamepadPlatformService::GetParentService();
if (!service) {
return;
}
for (size_t i = 0; i < mGamepads.size(); i++) {
if (mGamepads[i] == device) {
service->RemoveGamepad(mGamepads[i].mSuperIndex);
mGamepads[i].clear();
return;
}
}
}
/*
* Given a value from a d-pad (POV hat in USB HID terminology),
* represent it as 4 buttons, one for each cardinal direction.
*/
static void
UnpackDpad(int dpad_value, int min, int max, dpad_buttons& buttons)
{
const unsigned kUp = 0;
const unsigned kDown = 1;
const unsigned kLeft = 2;
const unsigned kRight = 3;
// Different controllers have different ways of representing
// "nothing is pressed", but they're all outside the range of values.
if (dpad_value < min || dpad_value > max) {
// Nothing is pressed.
return;
}
// Normalize value to start at 0.
int value = dpad_value - min;
// Value will be in the range 0-7. The value represents the
// position of the d-pad around a circle, with 0 being straight up,
// 2 being right, 4 being straight down, and 6 being left.
if (value < 2 || value > 6) {
buttons[kUp] = true;
}
if (value > 2 && value < 6) {
buttons[kDown] = true;
}
if (value > 4) {
buttons[kLeft] = true;
}
if (value > 0 && value < 4) {
buttons[kRight] = true;
}
}
void
DarwinGamepadService::InputValueChanged(IOHIDValueRef value)
{
RefPtr<GamepadPlatformService> service =
GamepadPlatformService::GetParentService();
if (!service) {
return;
}
uint32_t value_length = IOHIDValueGetLength(value);
if (value_length > 4) {
// Workaround for bizarre issue with PS3 controllers that try to return
// massive (30+ byte) values and crash IOHIDValueGetIntegerValue
return;
}
IOHIDElementRef element = IOHIDValueGetElement(value);
IOHIDDeviceRef device = IOHIDElementGetDevice(element);
for (unsigned i = 0; i < mGamepads.size(); i++) {
Gamepad &gamepad = mGamepads[i];
if (gamepad == device) {
if (gamepad.isDpad(element)) {
const dpad_buttons& oldState = gamepad.getDpadState();
dpad_buttons newState = { false, false, false, false };
UnpackDpad(IOHIDValueGetIntegerValue(value),
IOHIDElementGetLogicalMin(element),
IOHIDElementGetLogicalMax(element),
newState);
const int numButtons = gamepad.numButtons();
for (unsigned b = 0; b < ArrayLength(newState); b++) {
if (newState[b] != oldState[b]) {
service->NewButtonEvent(gamepad.mSuperIndex,
numButtons - 4 + b,
newState[b]);
}
}
gamepad.setDpadState(newState);
} else if (const Axis* axis = gamepad.lookupAxis(element)) {
double d = IOHIDValueGetIntegerValue(value);
double v = 2.0f * (d - axis->min) /
(double)(axis->max - axis->min) - 1.0f;
service->NewAxisMoveEvent(gamepad.mSuperIndex, axis->id, v);
} else if (const Button* button = gamepad.lookupButton(element)) {
int iv = IOHIDValueGetIntegerValue(value);
bool pressed = iv != 0;
double v = 0;
if (button->analog) {
double dv = iv;
v = (dv - button->min) / (double)(button->max - button->min);
} else {
v = pressed ? 1.0 : 0.0;
}
service->NewButtonEvent(gamepad.mSuperIndex, button->id, pressed, v);
}
return;
}
}
}
void
DarwinGamepadService::DeviceAddedCallback(void* data, IOReturn result,
void* sender, IOHIDDeviceRef device)
{
DarwinGamepadService* service = (DarwinGamepadService*)data;
service->DeviceAdded(device);
}
void
DarwinGamepadService::DeviceRemovedCallback(void* data, IOReturn result,
void* sender, IOHIDDeviceRef device)
{
DarwinGamepadService* service = (DarwinGamepadService*)data;
service->DeviceRemoved(device);
}
void
DarwinGamepadService::InputValueChangedCallback(void* data,
IOReturn result,
void* sender,
IOHIDValueRef newValue)
{
DarwinGamepadService* service = (DarwinGamepadService*)data;
service->InputValueChanged(newValue);
}
static CFMutableDictionaryRef
MatchingDictionary(UInt32 inUsagePage, UInt32 inUsage)
{
CFMutableDictionaryRef dict =
CFDictionaryCreateMutable(kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (!dict)
return nullptr;
CFNumberRef number = CFNumberCreate(kCFAllocatorDefault,
kCFNumberIntType,
&inUsagePage);
if (!number) {
CFRelease(dict);
return nullptr;
}
CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsagePageKey), number);
CFRelease(number);
number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &inUsage);
if (!number) {
CFRelease(dict);
return nullptr;
}
CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsageKey), number);
CFRelease(number);
return dict;
}
DarwinGamepadService::DarwinGamepadService() : mManager(nullptr) {}
DarwinGamepadService::~DarwinGamepadService()
{
if (mManager != nullptr)
CFRelease(mManager);
}
void
DarwinGamepadService::StartupInternal()
{
if (mManager != nullptr)
return;
IOHIDManagerRef manager = IOHIDManagerCreate(kCFAllocatorDefault,
kIOHIDOptionsTypeNone);
CFMutableDictionaryRef criteria_arr[2];
criteria_arr[0] = MatchingDictionary(kDesktopUsagePage,
kJoystickUsage);
if (!criteria_arr[0]) {
CFRelease(manager);
return;
}
criteria_arr[1] = MatchingDictionary(kDesktopUsagePage,
kGamepadUsage);
if (!criteria_arr[1]) {
CFRelease(criteria_arr[0]);
CFRelease(manager);
return;
}
CFArrayRef criteria =
CFArrayCreate(kCFAllocatorDefault, (const void**)criteria_arr, 2, nullptr);
if (!criteria) {
CFRelease(criteria_arr[1]);
CFRelease(criteria_arr[0]);
CFRelease(manager);
return;
}
IOHIDManagerSetDeviceMatchingMultiple(manager, criteria);
CFRelease(criteria);
CFRelease(criteria_arr[1]);
CFRelease(criteria_arr[0]);
IOHIDManagerRegisterDeviceMatchingCallback(manager,
DeviceAddedCallback,
this);
IOHIDManagerRegisterDeviceRemovalCallback(manager,
DeviceRemovedCallback,
this);
IOHIDManagerRegisterInputValueCallback(manager,
InputValueChangedCallback,
this);
IOHIDManagerScheduleWithRunLoop(manager,
CFRunLoopGetCurrent(),
kCFRunLoopDefaultMode);
IOReturn rv = IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone);
if (rv != kIOReturnSuccess) {
CFRelease(manager);
return;
}
mManager = manager;
// We held the handle of the CFRunLoop to make sure we
// can shut it down explicitly by CFRunLoopStop in another
// thread.
mMonitorRunLoop = CFRunLoopGetCurrent();
// CFRunLoopRun() is a blocking message loop when it's called in
// non-main thread so this thread cannot receive any other runnables
// and nsITimer timeout events after it's called.
CFRunLoopRun();
}
void DarwinGamepadService::Startup()
{
Unused << NS_NewThread(getter_AddRefs(mMonitorThread),
new DarwinGamepadServiceStartupRunnable(this));
}
void DarwinGamepadService::Shutdown()
{
IOHIDManagerRef manager = (IOHIDManagerRef)mManager;
CFRunLoopStop(mMonitorRunLoop);
if (manager) {
IOHIDManagerClose(manager, 0);
CFRelease(manager);
mManager = nullptr;
}
mMonitorThread->Shutdown();
}
} // namespace
namespace mozilla {
namespace dom {
DarwinGamepadService* gService = nullptr;
void StartGamepadMonitoring()
{
if (gService) {
return;
}
gService = new DarwinGamepadService();
gService->Startup();
}
void StopGamepadMonitoring()
{
if (!gService) {
return;
}
gService->Shutdown();
delete gService;
gService = nullptr;
}
} // namespace dom
} // namespace mozilla

View file

@ -48,10 +48,6 @@ if CONFIG['MOZ_GAMEPAD']:
SOURCES += [
'fallback/FallbackGamepad.cpp'
]
elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'cocoa':
SOURCES += [
'cocoa/CocoaGamepad.cpp'
]
elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'windows':
SOURCES += [
'windows/WindowsGamepad.cpp'

View file

@ -29,10 +29,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
LOCAL_INCLUDES += [
'/dom/system/android',
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
LOCAL_INCLUDES += [
'/dom/system/mac',
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
LOCAL_INCLUDES += [
'/dom/system/windows',

View file

@ -13,9 +13,6 @@ SOURCES += [
'../VideoSegment.cpp',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
UNIFIED_SOURCES += ['../systemservices/OSXRunLoopSingleton.cpp']
LOCAL_INCLUDES += [
'/caps',
'/dom/base',

View file

@ -1,44 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
/* 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/. */
#include "OSXRunLoopSingleton.h"
#include <mozilla/StaticMutex.h>
#include <AudioUnit/AudioUnit.h>
#include <CoreAudio/AudioHardware.h>
#include <CoreAudio/HostTime.h>
#include <CoreFoundation/CoreFoundation.h>
static bool gRunLoopSet = false;
static mozilla::StaticMutex gMutex;
void mozilla_set_coreaudio_notification_runloop_if_needed()
{
mozilla::StaticMutexAutoLock lock(gMutex);
if (gRunLoopSet) {
return;
}
/* This is needed so that AudioUnit listeners get called on this thread, and
* not the main thread. If we don't do that, they are not called, or a crash
* occur, depending on the OSX version. */
AudioObjectPropertyAddress runloop_address = {
kAudioHardwarePropertyRunLoop,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
CFRunLoopRef run_loop = nullptr;
OSStatus r;
r = AudioObjectSetPropertyData(kAudioObjectSystemObject,
&runloop_address,
0, NULL, sizeof(CFRunLoopRef), &run_loop);
if (r != noErr) {
NS_WARNING("Could not make global CoreAudio notifications use their own thread.");
}
gRunLoopSet = true;
}

View file

@ -1,25 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
/* 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/. */
#ifndef OSXRUNLOOPSINGLETON_H_
#define OSXRUNLOOPSINGLETON_H_
#include <mozilla/Types.h>
#if defined(__cplusplus)
extern "C" {
#endif
/* This function tells CoreAudio to use its own thread for device change
* notifications, and can be called from any thread without external
* synchronization. */
void MOZ_EXPORT
mozilla_set_coreaudio_notification_runloop_if_needed();
#if defined(__cplusplus)
}
#endif
#endif // OSXRUNLOOPSINGLETON_H_

View file

@ -38,10 +38,6 @@ if CONFIG['OS_TARGET'] == 'Android':
'OpenSLESProvider.cpp',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
SOURCES += ['OSXRunLoopSingleton.cpp']
EXPORTS += ['OSXRunLoopSingleton.h']
if CONFIG['_MSC_VER']:
DEFINES['__PRETTY_FUNCTION__'] = '__FUNCSIG__'

View file

@ -1,56 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "mozilla/ModuleUtils.h"
#include "nsIClassInfoImpl.h"
#include "OSXSpeechSynthesizerService.h"
using namespace mozilla::dom;
#define OSXSPEECHSYNTHESIZERSERVICE_CID \
{0x914e73b4, 0x6337, 0x4bef, {0x97, 0xf3, 0x4d, 0x06, 0x9e, 0x05, 0x3a, 0x12}}
#define OSXSPEECHSYNTHESIZERSERVICE_CONTRACTID "@mozilla.org/synthsystem;1"
// Defines OSXSpeechSynthesizerServiceConstructor
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(OSXSpeechSynthesizerService,
OSXSpeechSynthesizerService::GetInstanceForService)
// Defines kOSXSERVICE_CID
NS_DEFINE_NAMED_CID(OSXSPEECHSYNTHESIZERSERVICE_CID);
static const mozilla::Module::CIDEntry kCIDs[] = {
{ &kOSXSPEECHSYNTHESIZERSERVICE_CID, true, nullptr, OSXSpeechSynthesizerServiceConstructor },
{ nullptr }
};
static const mozilla::Module::ContractIDEntry kContracts[] = {
{ OSXSPEECHSYNTHESIZERSERVICE_CONTRACTID, &kOSXSPEECHSYNTHESIZERSERVICE_CID },
{ nullptr }
};
static const mozilla::Module::CategoryEntry kCategories[] = {
{ "speech-synth-started", "OSX Speech Synth", OSXSPEECHSYNTHESIZERSERVICE_CONTRACTID },
{ nullptr }
};
static void
UnloadOSXSpeechSynthesizerModule()
{
OSXSpeechSynthesizerService::Shutdown();
}
static const mozilla::Module kModule = {
mozilla::Module::kVersion,
kCIDs,
kContracts,
kCategories,
nullptr,
nullptr,
UnloadOSXSpeechSynthesizerModule
};
NSMODULE_DEFN(osxsynth) = &kModule;

View file

@ -1,43 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef mozilla_dom_OsxSpeechSynthesizerService_h
#define mozilla_dom_OsxSpeechSynthesizerService_h
#include "nsISpeechService.h"
#include "nsIObserver.h"
#include "mozilla/StaticPtr.h"
namespace mozilla {
namespace dom {
class OSXSpeechSynthesizerService final : public nsISpeechService
, public nsIObserver
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSISPEECHSERVICE
NS_DECL_NSIOBSERVER
bool Init();
static OSXSpeechSynthesizerService* GetInstance();
static already_AddRefed<OSXSpeechSynthesizerService> GetInstanceForService();
static void Shutdown();
private:
OSXSpeechSynthesizerService();
virtual ~OSXSpeechSynthesizerService();
bool RegisterVoices();
bool mInitialized;
static mozilla::StaticRefPtr<OSXSpeechSynthesizerService> sSingleton;
};
} // namespace dom
} // namespace mozilla
#endif

View file

@ -1,498 +0,0 @@
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "nsISupports.h"
#include "nsServiceManagerUtils.h"
#include "nsObjCExceptions.h"
#include "nsCocoaUtils.h"
#include "nsThreadUtils.h"
#include "mozilla/dom/nsSynthVoiceRegistry.h"
#include "mozilla/dom/nsSpeechTask.h"
#include "mozilla/Preferences.h"
#include "mozilla/Assertions.h"
#include "OSXSpeechSynthesizerService.h"
#import <Cocoa/Cocoa.h>
// We can escape the default delimiters ("[[" and "]]") by temporarily
// changing the delimiters just before they appear, and changing them back
// just after.
#define DLIM_ESCAPE_START "[[dlim (( ))]]"
#define DLIM_ESCAPE_END "((dlim [[ ]]))"
using namespace mozilla;
class SpeechTaskCallback final : public nsISpeechTaskCallback
{
public:
SpeechTaskCallback(nsISpeechTask* aTask,
NSSpeechSynthesizer* aSynth,
const nsTArray<size_t>& aOffsets)
: mTask(aTask)
, mSpeechSynthesizer(aSynth)
, mOffsets(aOffsets)
{
mStartingTime = TimeStamp::Now();
}
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(SpeechTaskCallback, nsISpeechTaskCallback)
NS_DECL_NSISPEECHTASKCALLBACK
void OnWillSpeakWord(uint32_t aIndex);
void OnError(uint32_t aIndex);
void OnDidFinishSpeaking();
private:
virtual ~SpeechTaskCallback()
{
[mSpeechSynthesizer release];
}
float GetTimeDurationFromStart();
nsCOMPtr<nsISpeechTask> mTask;
NSSpeechSynthesizer* mSpeechSynthesizer;
TimeStamp mStartingTime;
uint32_t mCurrentIndex;
nsTArray<size_t> mOffsets;
};
NS_IMPL_CYCLE_COLLECTION(SpeechTaskCallback, mTask);
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SpeechTaskCallback)
NS_INTERFACE_MAP_ENTRY(nsISpeechTaskCallback)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISpeechTaskCallback)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(SpeechTaskCallback)
NS_IMPL_CYCLE_COLLECTING_RELEASE(SpeechTaskCallback)
NS_IMETHODIMP
SpeechTaskCallback::OnCancel()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
[mSpeechSynthesizer stopSpeaking];
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP
SpeechTaskCallback::OnPause()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
[mSpeechSynthesizer pauseSpeakingAtBoundary:NSSpeechImmediateBoundary];
if (!mTask) {
// When calling pause() on child porcess, it may not receive end event
// from chrome process yet.
return NS_ERROR_FAILURE;
}
mTask->DispatchPause(GetTimeDurationFromStart(), mCurrentIndex);
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP
SpeechTaskCallback::OnResume()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
[mSpeechSynthesizer continueSpeaking];
if (!mTask) {
// When calling resume() on child porcess, it may not receive end event
// from chrome process yet.
return NS_ERROR_FAILURE;
}
mTask->DispatchResume(GetTimeDurationFromStart(), mCurrentIndex);
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP
SpeechTaskCallback::OnVolumeChanged(float aVolume)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
[mSpeechSynthesizer setObject:[NSNumber numberWithFloat:aVolume]
forProperty:NSSpeechVolumeProperty error:nil];
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
float
SpeechTaskCallback::GetTimeDurationFromStart()
{
TimeDuration duration = TimeStamp::Now() - mStartingTime;
return duration.ToMilliseconds();
}
void
SpeechTaskCallback::OnWillSpeakWord(uint32_t aIndex)
{
mCurrentIndex = aIndex < mOffsets.Length() ? mOffsets[aIndex] : mCurrentIndex;
if (!mTask) {
return;
}
mTask->DispatchBoundary(NS_LITERAL_STRING("word"),
GetTimeDurationFromStart(), mCurrentIndex);
}
void
SpeechTaskCallback::OnError(uint32_t aIndex)
{
if (!mTask) {
return;
}
mTask->DispatchError(GetTimeDurationFromStart(), aIndex);
}
void
SpeechTaskCallback::OnDidFinishSpeaking()
{
mTask->DispatchEnd(GetTimeDurationFromStart(), mCurrentIndex);
// no longer needed
[mSpeechSynthesizer setDelegate:nil];
mTask = nullptr;
}
@interface SpeechDelegate : NSObject<NSSpeechSynthesizerDelegate>
{
@private
SpeechTaskCallback* mCallback;
}
- (id)initWithCallback:(SpeechTaskCallback*)aCallback;
@end
@implementation SpeechDelegate
- (id)initWithCallback:(SpeechTaskCallback*)aCallback
{
[super init];
mCallback = aCallback;
return self;
}
- (void)speechSynthesizer:(NSSpeechSynthesizer *)aSender
willSpeakWord:(NSRange)aRange ofString:(NSString*)aString
{
mCallback->OnWillSpeakWord(aRange.location);
}
- (void)speechSynthesizer:(NSSpeechSynthesizer *)aSender
didFinishSpeaking:(BOOL)aFinishedSpeaking
{
mCallback->OnDidFinishSpeaking();
}
- (void)speechSynthesizer:(NSSpeechSynthesizer*)aSender
didEncounterErrorAtIndex:(NSUInteger)aCharacterIndex
ofString:(NSString*)aString
message:(NSString*)aMessage
{
mCallback->OnError(aCharacterIndex);
}
@end
namespace mozilla {
namespace dom {
struct OSXVoice
{
OSXVoice() : mIsDefault(false)
{
}
nsString mUri;
nsString mName;
nsString mLocale;
bool mIsDefault;
};
class RegisterVoicesRunnable final : public Runnable
{
public:
RegisterVoicesRunnable(OSXSpeechSynthesizerService* aSpeechService,
nsTArray<OSXVoice>& aList)
: mSpeechService(aSpeechService)
, mVoices(aList)
{
}
NS_IMETHOD Run() override;
private:
~RegisterVoicesRunnable()
{
}
// This runnable always use sync mode. It is unnecesarry to reference object
OSXSpeechSynthesizerService* mSpeechService;
nsTArray<OSXVoice>& mVoices;
};
NS_IMETHODIMP
RegisterVoicesRunnable::Run()
{
nsresult rv;
nsCOMPtr<nsISynthVoiceRegistry> registry =
do_GetService(NS_SYNTHVOICEREGISTRY_CONTRACTID, &rv);
if (!registry) {
return rv;
}
for (OSXVoice voice : mVoices) {
rv = registry->AddVoice(mSpeechService, voice.mUri, voice.mName, voice.mLocale, true, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
continue;
}
if (voice.mIsDefault) {
registry->SetDefaultVoice(voice.mUri, true);
}
}
registry->NotifyVoicesChanged();
return NS_OK;
}
class EnumVoicesRunnable final : public Runnable
{
public:
explicit EnumVoicesRunnable(OSXSpeechSynthesizerService* aSpeechService)
: mSpeechService(aSpeechService)
{
}
NS_IMETHOD Run() override;
private:
~EnumVoicesRunnable()
{
}
RefPtr<OSXSpeechSynthesizerService> mSpeechService;
};
NS_IMETHODIMP
EnumVoicesRunnable::Run()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
AutoTArray<OSXVoice, 64> list;
NSArray* voices = [NSSpeechSynthesizer availableVoices];
NSString* defaultVoice = [NSSpeechSynthesizer defaultVoice];
for (NSString* voice in voices) {
OSXVoice item;
NSDictionary* attr = [NSSpeechSynthesizer attributesForVoice:voice];
nsAutoString identifier;
nsCocoaUtils::GetStringForNSString([attr objectForKey:NSVoiceIdentifier],
identifier);
nsCocoaUtils::GetStringForNSString([attr objectForKey:NSVoiceName], item.mName);
nsCocoaUtils::GetStringForNSString(
[attr objectForKey:NSVoiceLocaleIdentifier], item.mLocale);
item.mLocale.ReplaceChar('_', '-');
item.mUri.AssignLiteral("urn:moz-tts:osx:");
item.mUri.Append(identifier);
if ([voice isEqualToString:defaultVoice]) {
item.mIsDefault = true;
}
list.AppendElement(item);
}
RefPtr<RegisterVoicesRunnable> runnable = new RegisterVoicesRunnable(mSpeechService, list);
NS_DispatchToMainThread(runnable, NS_DISPATCH_SYNC);
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
StaticRefPtr<OSXSpeechSynthesizerService> OSXSpeechSynthesizerService::sSingleton;
NS_INTERFACE_MAP_BEGIN(OSXSpeechSynthesizerService)
NS_INTERFACE_MAP_ENTRY(nsISpeechService)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISpeechService)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(OSXSpeechSynthesizerService)
NS_IMPL_RELEASE(OSXSpeechSynthesizerService)
OSXSpeechSynthesizerService::OSXSpeechSynthesizerService()
: mInitialized(false)
{
}
OSXSpeechSynthesizerService::~OSXSpeechSynthesizerService()
{
}
bool
OSXSpeechSynthesizerService::Init()
{
if (Preferences::GetBool("media.webspeech.synth.test") ||
!Preferences::GetBool("media.webspeech.synth.enabled")) {
// When test is enabled, we shouldn't add OS backend (Bug 1160844)
return false;
}
nsCOMPtr<nsIThread> thread;
if (NS_FAILED(NS_NewNamedThread("SpeechWorker", getter_AddRefs(thread)))) {
return false;
}
// Get all the voices and register in the SynthVoiceRegistry
nsCOMPtr<nsIRunnable> runnable = new EnumVoicesRunnable(this);
thread->Dispatch(runnable, NS_DISPATCH_NORMAL);
mInitialized = true;
return true;
}
NS_IMETHODIMP
OSXSpeechSynthesizerService::Speak(const nsAString& aText,
const nsAString& aUri,
float aVolume,
float aRate,
float aPitch,
nsISpeechTask* aTask)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
MOZ_ASSERT(StringBeginsWith(aUri, NS_LITERAL_STRING("urn:moz-tts:osx:")),
"OSXSpeechSynthesizerService doesn't allow this voice URI");
NSSpeechSynthesizer* synth = [[NSSpeechSynthesizer alloc] init];
// strlen("urn:moz-tts:osx:") == 16
NSString* identifier = nsCocoaUtils::ToNSString(Substring(aUri, 16));
[synth setVoice:identifier];
// default rate is 180-220
[synth setObject:[NSNumber numberWithInt:aRate * 200]
forProperty:NSSpeechRateProperty error:nil];
// volume allows 0.0-1.0
[synth setObject:[NSNumber numberWithFloat:aVolume]
forProperty:NSSpeechVolumeProperty error:nil];
// Use default pitch value to calculate this
NSNumber* defaultPitch =
[synth objectForProperty:NSSpeechPitchBaseProperty error:nil];
if (defaultPitch) {
int newPitch = [defaultPitch intValue] * (aPitch / 2 + 0.5);
[synth setObject:[NSNumber numberWithInt:newPitch]
forProperty:NSSpeechPitchBaseProperty error:nil];
}
nsAutoString escapedText;
// We need to map the the offsets from the given text to the escaped text.
// The index of the offsets array is the position in the escaped text,
// the element value is the position in the user-supplied text.
nsTArray<size_t> offsets;
offsets.SetCapacity(aText.Length());
// This loop looks for occurances of "[[" or "]]", escapes them, and
// populates the offsets array to supply a map to the original offsets.
for (size_t i = 0; i < aText.Length(); i++) {
if (aText.Length() > i + 1 &&
((aText[i] == ']' && aText[i+1] == ']') ||
(aText[i] == '[' && aText[i+1] == '['))) {
escapedText.AppendLiteral(DLIM_ESCAPE_START);
offsets.AppendElements(strlen(DLIM_ESCAPE_START));
escapedText.Append(aText[i]);
offsets.AppendElement(i);
escapedText.Append(aText[++i]);
offsets.AppendElement(i);
escapedText.AppendLiteral(DLIM_ESCAPE_END);
offsets.AppendElements(strlen(DLIM_ESCAPE_END));
} else {
escapedText.Append(aText[i]);
offsets.AppendElement(i);
}
}
RefPtr<SpeechTaskCallback> callback = new SpeechTaskCallback(aTask, synth, offsets);
nsresult rv = aTask->Setup(callback, 0, 0, 0);
NS_ENSURE_SUCCESS(rv, rv);
SpeechDelegate* delegate = [[SpeechDelegate alloc] initWithCallback:callback];
[synth setDelegate:delegate];
[delegate release ];
NSString* text = nsCocoaUtils::ToNSString(escapedText);
BOOL success = [synth startSpeakingString:text];
NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
aTask->DispatchStart();
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP
OSXSpeechSynthesizerService::GetServiceType(SpeechServiceType* aServiceType)
{
*aServiceType = nsISpeechService::SERVICETYPE_INDIRECT_AUDIO;
return NS_OK;
}
NS_IMETHODIMP
OSXSpeechSynthesizerService::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData)
{
return NS_OK;
}
OSXSpeechSynthesizerService*
OSXSpeechSynthesizerService::GetInstance()
{
MOZ_ASSERT(NS_IsMainThread());
if (XRE_GetProcessType() != GeckoProcessType_Default) {
return nullptr;
}
if (!sSingleton) {
RefPtr<OSXSpeechSynthesizerService> speechService =
new OSXSpeechSynthesizerService();
if (speechService->Init()) {
sSingleton = speechService;
}
}
return sSingleton;
}
already_AddRefed<OSXSpeechSynthesizerService>
OSXSpeechSynthesizerService::GetInstanceForService()
{
RefPtr<OSXSpeechSynthesizerService> speechService = GetInstance();
return speechService.forget();
}
void
OSXSpeechSynthesizerService::Shutdown()
{
if (!sSingleton) {
return;
}
sSingleton = nullptr;
}
} // namespace dom
} // namespace mozilla

View file

@ -1,11 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# 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/.
SOURCES += [
'OSXSpeechSynthesizerModule.cpp',
'OSXSpeechSynthesizerService.mm'
]
FINAL_LIBRARY = 'xul'

View file

@ -32,9 +32,6 @@ SOURCES += [
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
DIRS += ['windows']
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
DIRS += ['cocoa']
if CONFIG['MOZ_SYNTH_SPEECHD']:
DIRS += ['speechd']

View file

@ -112,6 +112,6 @@ TEST_DIRS += [
'imptests',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3', 'cocoa', 'windows', 'android'):
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3', 'windows', 'android'):
TEST_DIRS += ['plugins/test']

View file

@ -56,11 +56,6 @@ if CONFIG['OS_ARCH'] == 'WINNT':
'nsPluginNativeWindowWin.cpp',
'nsPluginsDirWin.cpp',
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
SOURCES += [
'nsPluginNativeWindow.cpp',
'nsPluginsDirDarwin.cpp',
]
else:
SOURCES += [
'nsPluginsDirUnix.cpp',
@ -82,7 +77,6 @@ LOCAL_INCLUDES += [
'/layout/xul',
'/netwerk/base',
'/widget',
'/widget/cocoa',
'/xpcom/base',
]

View file

@ -1,572 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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/. */
/*
nsPluginsDirDarwin.cpp
Mac OS X implementation of the nsPluginsDir/nsPluginsFile classes.
by Patrick C. Beard.
*/
#include "GeckoChildProcessHost.h"
#include "base/process_util.h"
#include "prlink.h"
#include "prnetdb.h"
#include "nsXPCOM.h"
#include "nsPluginsDir.h"
#include "nsNPAPIPlugin.h"
#include "nsPluginsDirUtils.h"
#include "nsILocalFileMac.h"
#include "mozilla/UniquePtr.h"
#include "nsCocoaFeatures.h"
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <Carbon/Carbon.h>
#include <CoreServices/CoreServices.h>
#include <mach-o/loader.h>
#include <mach-o/fat.h>
typedef NS_NPAPIPLUGIN_CALLBACK(const char *, NP_GETMIMEDESCRIPTION) ();
typedef NS_NPAPIPLUGIN_CALLBACK(OSErr, BP_GETSUPPORTEDMIMETYPES) (BPSupportedMIMETypes *mimeInfo, UInt32 flags);
/*
** Returns a CFBundleRef if the path refers to a Mac OS X bundle directory.
** The caller is responsible for calling CFRelease() to deallocate.
*/
static CFBundleRef getPluginBundle(const char* path)
{
CFBundleRef bundle = nullptr;
CFStringRef pathRef = ::CFStringCreateWithCString(nullptr, path,
kCFStringEncodingUTF8);
if (pathRef) {
CFURLRef bundleURL = ::CFURLCreateWithFileSystemPath(nullptr, pathRef,
kCFURLPOSIXPathStyle,
true);
if (bundleURL) {
bundle = ::CFBundleCreate(nullptr, bundleURL);
::CFRelease(bundleURL);
}
::CFRelease(pathRef);
}
return bundle;
}
static nsresult toCFURLRef(nsIFile* file, CFURLRef& outURL)
{
nsCOMPtr<nsILocalFileMac> lfm = do_QueryInterface(file);
if (!lfm)
return NS_ERROR_FAILURE;
CFURLRef url;
nsresult rv = lfm->GetCFURL(&url);
if (NS_SUCCEEDED(rv))
outURL = url;
return rv;
}
bool nsPluginsDir::IsPluginFile(nsIFile* file)
{
nsCString fileName;
file->GetNativeLeafName(fileName);
/*
* Don't load the VDP fake plugin, to avoid tripping a bad bug in OS X
* 10.5.3 (see bug 436575).
*/
if (!strcmp(fileName.get(), "VerifiedDownloadPlugin.plugin")) {
NS_WARNING("Preventing load of VerifiedDownloadPlugin.plugin (see bug 436575)");
return false;
}
return true;
}
// Caller is responsible for freeing returned buffer.
static char* CFStringRefToUTF8Buffer(CFStringRef cfString)
{
const char* buffer = ::CFStringGetCStringPtr(cfString, kCFStringEncodingUTF8);
if (buffer) {
return PL_strdup(buffer);
}
int bufferLength =
::CFStringGetMaximumSizeForEncoding(::CFStringGetLength(cfString),
kCFStringEncodingUTF8) + 1;
char* newBuffer = static_cast<char*>(moz_xmalloc(bufferLength));
if (!newBuffer) {
return nullptr;
}
if (!::CFStringGetCString(cfString, newBuffer, bufferLength,
kCFStringEncodingUTF8)) {
free(newBuffer);
return nullptr;
}
newBuffer = static_cast<char*>(moz_xrealloc(newBuffer,
strlen(newBuffer) + 1));
return newBuffer;
}
class AutoCFTypeObject {
public:
explicit AutoCFTypeObject(CFTypeRef aObject)
{
mObject = aObject;
}
~AutoCFTypeObject()
{
::CFRelease(mObject);
}
private:
CFTypeRef mObject;
};
static Boolean MimeTypeEnabled(CFDictionaryRef mimeDict) {
if (!mimeDict) {
return true;
}
CFTypeRef value;
if (::CFDictionaryGetValueIfPresent(mimeDict, CFSTR("WebPluginTypeEnabled"), &value)) {
if (value && ::CFGetTypeID(value) == ::CFBooleanGetTypeID()) {
return ::CFBooleanGetValue(static_cast<CFBooleanRef>(value));
}
}
return true;
}
static CFDictionaryRef ParsePlistForMIMETypesFilename(CFBundleRef bundle)
{
CFTypeRef mimeFileName = ::CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("WebPluginMIMETypesFilename"));
if (!mimeFileName || ::CFGetTypeID(mimeFileName) != ::CFStringGetTypeID()) {
return nullptr;
}
FSRef homeDir;
if (::FSFindFolder(kUserDomain, kCurrentUserFolderType, kDontCreateFolder, &homeDir) != noErr) {
return nullptr;
}
CFURLRef userDirURL = ::CFURLCreateFromFSRef(kCFAllocatorDefault, &homeDir);
if (!userDirURL) {
return nullptr;
}
AutoCFTypeObject userDirURLAutorelease(userDirURL);
CFStringRef mimeFilePath = ::CFStringCreateWithFormat(kCFAllocatorDefault, nullptr, CFSTR("Library/Preferences/%@"), static_cast<CFStringRef>(mimeFileName));
if (!mimeFilePath) {
return nullptr;
}
AutoCFTypeObject mimeFilePathAutorelease(mimeFilePath);
CFURLRef mimeFileURL = ::CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorDefault, mimeFilePath, kCFURLPOSIXPathStyle, false, userDirURL);
if (!mimeFileURL) {
return nullptr;
}
AutoCFTypeObject mimeFileURLAutorelease(mimeFileURL);
SInt32 errorCode = 0;
CFDataRef mimeFileData = nullptr;
Boolean result = ::CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, mimeFileURL, &mimeFileData, nullptr, nullptr, &errorCode);
if (!result) {
return nullptr;
}
AutoCFTypeObject mimeFileDataAutorelease(mimeFileData);
if (errorCode != 0) {
return nullptr;
}
CFPropertyListRef propertyList = ::CFPropertyListCreateFromXMLData(kCFAllocatorDefault, mimeFileData, kCFPropertyListImmutable, nullptr);
if (!propertyList) {
return nullptr;
}
AutoCFTypeObject propertyListAutorelease(propertyList);
if (::CFGetTypeID(propertyList) != ::CFDictionaryGetTypeID()) {
return nullptr;
}
CFTypeRef mimeTypes = ::CFDictionaryGetValue(static_cast<CFDictionaryRef>(propertyList), CFSTR("WebPluginMIMETypes"));
if (!mimeTypes || ::CFGetTypeID(mimeTypes) != ::CFDictionaryGetTypeID() || ::CFDictionaryGetCount(static_cast<CFDictionaryRef>(mimeTypes)) == 0) {
return nullptr;
}
return static_cast<CFDictionaryRef>(::CFRetain(mimeTypes));
}
static void ParsePlistPluginInfo(nsPluginInfo& info, CFBundleRef bundle)
{
CFDictionaryRef mimeDict = ParsePlistForMIMETypesFilename(bundle);
if (!mimeDict) {
CFTypeRef mimeTypes = ::CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("WebPluginMIMETypes"));
if (!mimeTypes || ::CFGetTypeID(mimeTypes) != ::CFDictionaryGetTypeID() || ::CFDictionaryGetCount(static_cast<CFDictionaryRef>(mimeTypes)) == 0)
return;
mimeDict = static_cast<CFDictionaryRef>(::CFRetain(mimeTypes));
}
AutoCFTypeObject mimeDictAutorelease(mimeDict);
int mimeDictKeyCount = ::CFDictionaryGetCount(mimeDict);
// Allocate memory for mime data
int mimeDataArraySize = mimeDictKeyCount * sizeof(char*);
info.fMimeTypeArray = static_cast<char**>(moz_xmalloc(mimeDataArraySize));
if (!info.fMimeTypeArray)
return;
memset(info.fMimeTypeArray, 0, mimeDataArraySize);
info.fExtensionArray = static_cast<char**>(moz_xmalloc(mimeDataArraySize));
if (!info.fExtensionArray)
return;
memset(info.fExtensionArray, 0, mimeDataArraySize);
info.fMimeDescriptionArray = static_cast<char**>(moz_xmalloc(mimeDataArraySize));
if (!info.fMimeDescriptionArray)
return;
memset(info.fMimeDescriptionArray, 0, mimeDataArraySize);
// Allocate memory for mime dictionary keys and values
mozilla::UniquePtr<CFTypeRef[]> keys(new CFTypeRef[mimeDictKeyCount]);
if (!keys)
return;
mozilla::UniquePtr<CFTypeRef[]> values(new CFTypeRef[mimeDictKeyCount]);
if (!values)
return;
info.fVariantCount = 0;
::CFDictionaryGetKeysAndValues(mimeDict, keys.get(), values.get());
for (int i = 0; i < mimeDictKeyCount; i++) {
CFTypeRef mimeString = keys[i];
if (!mimeString || ::CFGetTypeID(mimeString) != ::CFStringGetTypeID()) {
continue;
}
CFTypeRef mimeDict = values[i];
if (mimeDict && ::CFGetTypeID(mimeDict) == ::CFDictionaryGetTypeID()) {
if (!MimeTypeEnabled(static_cast<CFDictionaryRef>(mimeDict))) {
continue;
}
info.fMimeTypeArray[info.fVariantCount] = CFStringRefToUTF8Buffer(static_cast<CFStringRef>(mimeString));
if (!info.fMimeTypeArray[info.fVariantCount]) {
continue;
}
CFTypeRef extensions = ::CFDictionaryGetValue(static_cast<CFDictionaryRef>(mimeDict), CFSTR("WebPluginExtensions"));
if (extensions && ::CFGetTypeID(extensions) == ::CFArrayGetTypeID()) {
int extensionCount = ::CFArrayGetCount(static_cast<CFArrayRef>(extensions));
CFMutableStringRef extensionList = ::CFStringCreateMutable(kCFAllocatorDefault, 0);
for (int j = 0; j < extensionCount; j++) {
CFTypeRef extension = ::CFArrayGetValueAtIndex(static_cast<CFArrayRef>(extensions), j);
if (extension && ::CFGetTypeID(extension) == ::CFStringGetTypeID()) {
if (j > 0)
::CFStringAppend(extensionList, CFSTR(","));
::CFStringAppend(static_cast<CFMutableStringRef>(extensionList), static_cast<CFStringRef>(extension));
}
}
info.fExtensionArray[info.fVariantCount] = CFStringRefToUTF8Buffer(static_cast<CFStringRef>(extensionList));
::CFRelease(extensionList);
}
CFTypeRef description = ::CFDictionaryGetValue(static_cast<CFDictionaryRef>(mimeDict), CFSTR("WebPluginTypeDescription"));
if (description && ::CFGetTypeID(description) == ::CFStringGetTypeID())
info.fMimeDescriptionArray[info.fVariantCount] = CFStringRefToUTF8Buffer(static_cast<CFStringRef>(description));
}
info.fVariantCount++;
}
}
nsPluginFile::nsPluginFile(nsIFile *spec)
: mPlugin(spec)
{
}
nsPluginFile::~nsPluginFile() {}
nsresult nsPluginFile::LoadPlugin(PRLibrary **outLibrary)
{
if (!mPlugin)
return NS_ERROR_NULL_POINTER;
// 64-bit NSPR does not (yet) support bundles. So in 64-bit builds we need
// (for now) to load the bundle's executable. However this can cause
// problems: CFBundleCreate() doesn't run the bundle's executable's
// initialization code, while NSAddImage() and dlopen() do run it. So using
// NSPR's dyld loading mechanisms here (NSAddImage() or dlopen()) can cause
// a bundle's initialization code to run earlier than expected, and lead to
// crashes. See bug 577967.
#ifdef __LP64__
char executablePath[PATH_MAX];
executablePath[0] = '\0';
nsAutoCString bundlePath;
mPlugin->GetNativePath(bundlePath);
CFStringRef pathRef = ::CFStringCreateWithCString(nullptr, bundlePath.get(),
kCFStringEncodingUTF8);
if (pathRef) {
CFURLRef bundleURL = ::CFURLCreateWithFileSystemPath(nullptr, pathRef,
kCFURLPOSIXPathStyle,
true);
if (bundleURL) {
CFBundleRef bundle = ::CFBundleCreate(nullptr, bundleURL);
if (bundle) {
CFURLRef executableURL = ::CFBundleCopyExecutableURL(bundle);
if (executableURL) {
if (!::CFURLGetFileSystemRepresentation(executableURL, true, (UInt8*)&executablePath, PATH_MAX))
executablePath[0] = '\0';
::CFRelease(executableURL);
}
::CFRelease(bundle);
}
::CFRelease(bundleURL);
}
::CFRelease(pathRef);
}
#else
nsAutoCString bundlePath;
mPlugin->GetNativePath(bundlePath);
const char *executablePath = bundlePath.get();
#endif
*outLibrary = PR_LoadLibrary(executablePath);
pLibrary = *outLibrary;
if (!pLibrary) {
return NS_ERROR_FAILURE;
}
#ifdef DEBUG
printf("[loaded plugin %s]\n", bundlePath.get());
#endif
return NS_OK;
}
static char* p2cstrdup(StringPtr pstr)
{
int len = pstr[0];
char* cstr = static_cast<char*>(moz_xmalloc(len + 1));
if (cstr) {
memmove(cstr, pstr + 1, len);
cstr[len] = '\0';
}
return cstr;
}
static char* GetNextPluginStringFromHandle(Handle h, short *index)
{
char *ret = p2cstrdup((unsigned char*)(*h + *index));
*index += (ret ? strlen(ret) : 0) + 1;
return ret;
}
static bool IsCompatibleArch(nsIFile *file)
{
CFURLRef pluginURL = nullptr;
if (NS_FAILED(toCFURLRef(file, pluginURL)))
return false;
bool isPluginFile = false;
CFBundleRef pluginBundle = ::CFBundleCreate(kCFAllocatorDefault, pluginURL);
if (pluginBundle) {
UInt32 packageType, packageCreator;
::CFBundleGetPackageInfo(pluginBundle, &packageType, &packageCreator);
if (packageType == 'BRPL' || packageType == 'IEPL' || packageType == 'NSPL') {
// Get path to plugin as a C string.
char executablePath[PATH_MAX];
executablePath[0] = '\0';
if (!::CFURLGetFileSystemRepresentation(pluginURL, true, (UInt8*)&executablePath, PATH_MAX)) {
executablePath[0] = '\0';
}
uint32_t pluginLibArchitectures;
nsresult rv = mozilla::ipc::GeckoChildProcessHost::GetArchitecturesForBinary(executablePath, &pluginLibArchitectures);
if (NS_FAILED(rv)) {
return false;
}
uint32_t supportedArchitectures =
#ifdef __LP64__
mozilla::ipc::GeckoChildProcessHost::GetSupportedArchitecturesForProcessType(GeckoProcessType_Plugin);
#else
base::GetCurrentProcessArchitecture();
#endif
// Consider the plugin architecture valid if there is any overlap in the masks.
isPluginFile = !!(supportedArchitectures & pluginLibArchitectures);
}
::CFRelease(pluginBundle);
}
::CFRelease(pluginURL);
return isPluginFile;
}
/**
* Obtains all of the information currently available for this plugin.
*/
nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info, PRLibrary **outLibrary)
{
*outLibrary = nullptr;
nsresult rv = NS_OK;
if (!IsCompatibleArch(mPlugin)) {
return NS_ERROR_FAILURE;
}
// clear out the info, except for the first field.
memset(&info, 0, sizeof(info));
// Try to get a bundle reference.
nsAutoCString path;
if (NS_FAILED(rv = mPlugin->GetNativePath(path)))
return rv;
CFBundleRef bundle = getPluginBundle(path.get());
// fill in full path
info.fFullPath = PL_strdup(path.get());
// fill in file name
nsAutoCString fileName;
if (NS_FAILED(rv = mPlugin->GetNativeLeafName(fileName)))
return rv;
info.fFileName = PL_strdup(fileName.get());
// Get fName
if (bundle) {
CFTypeRef name = ::CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("WebPluginName"));
if (name && ::CFGetTypeID(name) == ::CFStringGetTypeID())
info.fName = CFStringRefToUTF8Buffer(static_cast<CFStringRef>(name));
}
// Get fDescription
if (bundle) {
CFTypeRef description = ::CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("WebPluginDescription"));
if (description && ::CFGetTypeID(description) == ::CFStringGetTypeID())
info.fDescription = CFStringRefToUTF8Buffer(static_cast<CFStringRef>(description));
}
// Get fVersion
if (bundle) {
// Look for the release version first
CFTypeRef version = ::CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("CFBundleShortVersionString"));
if (!version) // try the build version
version = ::CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleVersionKey);
if (version && ::CFGetTypeID(version) == ::CFStringGetTypeID())
info.fVersion = CFStringRefToUTF8Buffer(static_cast<CFStringRef>(version));
}
// The last thing we need to do is get MIME data
// fVariantCount, fMimeTypeArray, fExtensionArray, fMimeDescriptionArray
// First look for data in a bundle plist
if (bundle) {
ParsePlistPluginInfo(info, bundle);
::CFRelease(bundle);
if (info.fVariantCount > 0)
return NS_OK;
}
// Don't load "fbplugin" or any plugins whose name starts with "fbplugin_"
// (Facebook plugins) if we're running on OS X 10.10 (Yosemite) or later.
// A "fbplugin" file crashes on load, in the call to LoadPlugin() below.
// See bug 1086977.
if (nsCocoaFeatures::OnYosemiteOrLater()) {
if (fileName.EqualsLiteral("fbplugin") ||
StringBeginsWith(fileName, NS_LITERAL_CSTRING("fbplugin_"))) {
nsAutoCString msg;
msg.AppendPrintf("Preventing load of %s (see bug 1086977)",
fileName.get());
NS_WARNING(msg.get());
return NS_ERROR_FAILURE;
}
}
// It's possible that our plugin has 2 entry points that'll give us mime type
// info. Quicktime does this to get around the need of having admin rights to
// change mime info in the resource fork. We need to use this info instead of
// the resource. See bug 113464.
// Sadly we have to load the library for this to work.
rv = LoadPlugin(outLibrary);
if (NS_FAILED(rv))
return rv;
// Try to get data from NP_GetMIMEDescription
if (pLibrary) {
NP_GETMIMEDESCRIPTION pfnGetMimeDesc = (NP_GETMIMEDESCRIPTION)PR_FindFunctionSymbol(pLibrary, NP_GETMIMEDESCRIPTION_NAME);
if (pfnGetMimeDesc)
ParsePluginMimeDescription(pfnGetMimeDesc(), info);
if (info.fVariantCount)
return NS_OK;
}
// We'll fill this in using BP_GetSupportedMIMETypes and/or resource fork data
BPSupportedMIMETypes mi = {kBPSupportedMIMETypesStructVers_1, nullptr, nullptr};
// Try to get data from BP_GetSupportedMIMETypes
if (pLibrary) {
BP_GETSUPPORTEDMIMETYPES pfnMime = (BP_GETSUPPORTEDMIMETYPES)PR_FindFunctionSymbol(pLibrary, "BP_GetSupportedMIMETypes");
if (pfnMime && noErr == pfnMime(&mi, 0) && mi.typeStrings) {
info.fVariantCount = (**(short**)mi.typeStrings) / 2;
::HLock(mi.typeStrings);
if (mi.infoStrings) // it's possible some plugins have infoStrings missing
::HLock(mi.infoStrings);
}
}
// Fill in the info struct based on the data in the BPSupportedMIMETypes struct
int variantCount = info.fVariantCount;
info.fMimeTypeArray = static_cast<char**>(moz_xmalloc(variantCount * sizeof(char*)));
if (!info.fMimeTypeArray)
return NS_ERROR_OUT_OF_MEMORY;
info.fExtensionArray = static_cast<char**>(moz_xmalloc(variantCount * sizeof(char*)));
if (!info.fExtensionArray)
return NS_ERROR_OUT_OF_MEMORY;
if (mi.infoStrings) {
info.fMimeDescriptionArray = static_cast<char**>(moz_xmalloc(variantCount * sizeof(char*)));
if (!info.fMimeDescriptionArray)
return NS_ERROR_OUT_OF_MEMORY;
}
short mimeIndex = 2;
short descriptionIndex = 2;
for (int i = 0; i < variantCount; i++) {
info.fMimeTypeArray[i] = GetNextPluginStringFromHandle(mi.typeStrings, &mimeIndex);
info.fExtensionArray[i] = GetNextPluginStringFromHandle(mi.typeStrings, &mimeIndex);
if (mi.infoStrings)
info.fMimeDescriptionArray[i] = GetNextPluginStringFromHandle(mi.infoStrings, &descriptionIndex);
}
::HUnlock(mi.typeStrings);
::DisposeHandle(mi.typeStrings);
if (mi.infoStrings) {
::HUnlock(mi.infoStrings);
::DisposeHandle(mi.infoStrings);
}
return NS_OK;
}
nsresult nsPluginFile::FreePluginInfo(nsPluginInfo& info)
{
free(info.fName);
free(info.fDescription);
int variantCount = info.fVariantCount;
for (int i = 0; i < variantCount; i++) {
free(info.fMimeTypeArray[i]);
free(info.fExtensionArray[i]);
free(info.fMimeDescriptionArray[i]);
}
free(info.fMimeTypeArray);
free(info.fMimeDescriptionArray);
free(info.fExtensionArray);
free(info.fFileName);
free(info.fFullPath);
free(info.fVersion);
return NS_OK;
}

View file

@ -1,59 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "nsCOMPtr.h"
#include "nsIGeolocationProvider.h"
/*
* The CoreLocationObjects class contains the CoreLocation objects
* we'll need.
*
* Declaring them directly in CoreLocationLocationProvider
* would require Objective-C++ syntax, which would contaminate all
* files that include this header and require them to be Objective-C++
* as well.
*
* The solution then is to forward-declare CoreLocationObjects here and
* hold a pointer to it in CoreLocationLocationProvider, and only actually
* define it in CoreLocationLocationProvider.mm, thus making it safe
* for nsGeolocation.cpp, which is C++-only, to include this header.
*/
class CoreLocationObjects;
class MLSFallback;
class CoreLocationLocationProvider
: public nsIGeolocationProvider
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIGEOLOCATIONPROVIDER
CoreLocationLocationProvider();
void NotifyError(uint16_t aErrorCode);
void Update(nsIDOMGeoPosition* aSomewhere);
void CreateMLSFallbackProvider();
void CancelMLSFallbackProvider();
private:
virtual ~CoreLocationLocationProvider();
CoreLocationObjects* mCLObjects;
nsCOMPtr<nsIGeolocationUpdate> mCallback;
RefPtr<MLSFallback> mMLSFallbackProvider;
class MLSUpdate : public nsIGeolocationUpdate
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIGEOLOCATIONUPDATE
explicit MLSUpdate(CoreLocationLocationProvider& parentProvider);
private:
CoreLocationLocationProvider& mParentLocationProvider;
virtual ~MLSUpdate();
};
};

View file

@ -1,268 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsGeoPosition.h"
#include "nsIConsoleService.h"
#include "nsServiceManagerUtils.h"
#include "nsIDOMGeoPositionError.h"
#include "CoreLocationLocationProvider.h"
#include "nsCocoaFeatures.h"
#include "prtime.h"
#include "MLSFallback.h"
#include <CoreLocation/CLError.h>
#include <CoreLocation/CLLocation.h>
#include <CoreLocation/CLLocationManager.h>
#include <CoreLocation/CLLocationManagerDelegate.h>
#include <objc/objc.h>
#include <objc/objc-runtime.h>
#include "nsObjCExceptions.h"
using namespace mozilla;
static const CLLocationAccuracy kHIGH_ACCURACY = kCLLocationAccuracyBest;
static const CLLocationAccuracy kDEFAULT_ACCURACY = kCLLocationAccuracyNearestTenMeters;
@interface LocationDelegate : NSObject <CLLocationManagerDelegate>
{
CoreLocationLocationProvider* mProvider;
}
- (id)init:(CoreLocationLocationProvider*)aProvider;
- (void)locationManager:(CLLocationManager*)aManager
didFailWithError:(NSError *)aError;
- (void)locationManager:(CLLocationManager*)aManager didUpdateLocations:(NSArray*)locations;
@end
@implementation LocationDelegate
- (id) init:(CoreLocationLocationProvider*) aProvider
{
if ((self = [super init])) {
mProvider = aProvider;
}
return self;
}
- (void)locationManager:(CLLocationManager*)aManager
didFailWithError:(NSError *)aError
{
nsCOMPtr<nsIConsoleService> console =
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
NS_ENSURE_TRUE_VOID(console);
NSString* message =
[@"Failed to acquire position: " stringByAppendingString: [aError localizedDescription]];
console->LogStringMessage(NS_ConvertUTF8toUTF16([message UTF8String]).get());
if ([aError code] == kCLErrorDenied) {
mProvider->NotifyError(nsIDOMGeoPositionError::PERMISSION_DENIED);
return;
}
// The CL provider does not fallback to GeoIP, so use NetworkGeolocationProvider for this.
// The concept here is: on error, hand off geolocation to MLS, which will then report
// back a location or error. We can't call this with no delay however, as this method
// is called with an error code of 0 in both failed geolocation cases, and also when
// geolocation is not immediately available.
// The 2 sec delay is arbitrarily large enough that CL has a reasonable head start and
// if it is likely to succeed, it should complete before the MLS provider.
// Take note that in locationManager:didUpdateLocations: the handoff to MLS is stopped.
mProvider->CreateMLSFallbackProvider();
}
- (void)locationManager:(CLLocationManager*)aManager didUpdateLocations:(NSArray*)aLocations
{
if (aLocations.count < 1) {
return;
}
mProvider->CancelMLSFallbackProvider();
CLLocation* location = [aLocations objectAtIndex:0];
nsCOMPtr<nsIDOMGeoPosition> geoPosition =
new nsGeoPosition(location.coordinate.latitude,
location.coordinate.longitude,
location.altitude,
location.horizontalAccuracy,
location.verticalAccuracy,
location.course,
location.speed,
PR_Now() / PR_USEC_PER_MSEC);
mProvider->Update(geoPosition);
}
@end
NS_IMPL_ISUPPORTS(CoreLocationLocationProvider::MLSUpdate, nsIGeolocationUpdate);
CoreLocationLocationProvider::MLSUpdate::MLSUpdate(CoreLocationLocationProvider& parentProvider)
: mParentLocationProvider(parentProvider)
{
}
CoreLocationLocationProvider::MLSUpdate::~MLSUpdate()
{
}
NS_IMETHODIMP
CoreLocationLocationProvider::MLSUpdate::Update(nsIDOMGeoPosition *position)
{
nsCOMPtr<nsIDOMGeoPositionCoords> coords;
position->GetCoords(getter_AddRefs(coords));
if (!coords) {
return NS_ERROR_FAILURE;
}
mParentLocationProvider.Update(position);
return NS_OK;
}
NS_IMETHODIMP
CoreLocationLocationProvider::MLSUpdate::NotifyError(uint16_t error)
{
mParentLocationProvider.NotifyError(error);
return NS_OK;
}
class CoreLocationObjects {
public:
nsresult Init(CoreLocationLocationProvider* aProvider) {
mLocationManager = [[CLLocationManager alloc] init];
NS_ENSURE_TRUE(mLocationManager, NS_ERROR_NOT_AVAILABLE);
mLocationDelegate = [[LocationDelegate alloc] init:aProvider];
NS_ENSURE_TRUE(mLocationDelegate, NS_ERROR_NOT_AVAILABLE);
mLocationManager.desiredAccuracy = kDEFAULT_ACCURACY;
mLocationManager.delegate = mLocationDelegate;
return NS_OK;
}
~CoreLocationObjects() {
if (mLocationManager) {
[mLocationManager release];
}
if (mLocationDelegate) {
[mLocationDelegate release];
}
}
LocationDelegate* mLocationDelegate;
CLLocationManager* mLocationManager;
};
NS_IMPL_ISUPPORTS(CoreLocationLocationProvider, nsIGeolocationProvider)
CoreLocationLocationProvider::CoreLocationLocationProvider()
: mCLObjects(nullptr), mMLSFallbackProvider(nullptr)
{
}
CoreLocationLocationProvider::~CoreLocationLocationProvider()
{
}
NS_IMETHODIMP
CoreLocationLocationProvider::Startup()
{
if (!mCLObjects) {
nsAutoPtr<CoreLocationObjects> clObjs(new CoreLocationObjects());
nsresult rv = clObjs->Init(this);
NS_ENSURE_SUCCESS(rv, rv);
mCLObjects = clObjs.forget();
}
// Must be stopped before starting or response (success or failure) is not guaranteed
[mCLObjects->mLocationManager stopUpdatingLocation];
[mCLObjects->mLocationManager startUpdatingLocation];
return NS_OK;
}
NS_IMETHODIMP
CoreLocationLocationProvider::Watch(nsIGeolocationUpdate* aCallback)
{
if (mCallback) {
return NS_OK;
}
mCallback = aCallback;
return NS_OK;
}
NS_IMETHODIMP
CoreLocationLocationProvider::Shutdown()
{
NS_ENSURE_STATE(mCLObjects);
[mCLObjects->mLocationManager stopUpdatingLocation];
delete mCLObjects;
mCLObjects = nullptr;
if (mMLSFallbackProvider) {
mMLSFallbackProvider->Shutdown();
mMLSFallbackProvider = nullptr;
}
return NS_OK;
}
NS_IMETHODIMP
CoreLocationLocationProvider::SetHighAccuracy(bool aEnable)
{
NS_ENSURE_STATE(mCLObjects);
mCLObjects->mLocationManager.desiredAccuracy =
(aEnable ? kHIGH_ACCURACY : kDEFAULT_ACCURACY);
return NS_OK;
}
void
CoreLocationLocationProvider::Update(nsIDOMGeoPosition* aSomewhere)
{
if (aSomewhere && mCallback) {
mCallback->Update(aSomewhere);
}
}
void
CoreLocationLocationProvider::NotifyError(uint16_t aErrorCode)
{
mCallback->NotifyError(aErrorCode);
}
void
CoreLocationLocationProvider::CreateMLSFallbackProvider()
{
if (mMLSFallbackProvider) {
return;
}
mMLSFallbackProvider = new MLSFallback();
mMLSFallbackProvider->Startup(new MLSUpdate(*this));
}
void
CoreLocationLocationProvider::CancelMLSFallbackProvider()
{
if (!mMLSFallbackProvider) {
return;
}
mMLSFallbackProvider->Shutdown();
mMLSFallbackProvider = nullptr;
}

View file

@ -1,14 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# 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/.
SOURCES += ['CoreLocationLocationProvider.mm']
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'/dom/geolocation',
]

View file

@ -7,8 +7,6 @@ toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
if toolkit == 'windows':
DIRS += ['windows']
elif toolkit == 'cocoa':
DIRS += ['mac']
elif toolkit == 'android':
DIRS += ['android']
elif toolkit in ('gtk2', 'gtk3'):

View file

@ -1,6 +0,0 @@
# 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/.
toolkit.jar:
* content/global/platformHTMLBindings.xml (platformHTMLBindings.xml)

View file

@ -1,6 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# 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/.
JAR_MANIFESTS += ['jar.mn']

View file

@ -1,72 +0,0 @@
<?xml version="1.0"?>
<!-- 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/. -->
<bindings id="htmlBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="inputFields" bindToUntrustedContent="true">
<handlers>
<handler event="keypress" key="c" modifiers="accel" command="cmd_copy"/>
<handler event="keypress" key="x" modifiers="accel" command="cmd_cut"/>
<handler event="keypress" key="v" modifiers="accel" command="cmd_paste"/>
<handler event="keypress" key="z" modifiers="accel" command="cmd_undo"/>
<handler event="keypress" key="z" modifiers="accel,shift" command="cmd_redo"/>
<handler event="keypress" key="a" modifiers="accel" command="cmd_selectAll"/>
</handlers>
</binding>
<binding id="textAreas" bindToUntrustedContent="true">
<handlers>
<handler event="keypress" key="c" modifiers="accel" command="cmd_copy"/>
<handler event="keypress" key="x" modifiers="accel" command="cmd_cut"/>
<handler event="keypress" key="v" modifiers="accel" command="cmd_paste"/>
<handler event="keypress" key="z" modifiers="accel" command="cmd_undo"/>
<handler event="keypress" key="z" modifiers="accel,shift" command="cmd_redo"/>
<handler event="keypress" key="a" modifiers="accel" command="cmd_selectAll"/>
</handlers>
</binding>
<binding id="browser">
<handlers>
#include ../browser-base.inc
<handler event="keypress" keycode="VK_PAGE_UP" command="cmd_scrollPageUp"/>
<handler event="keypress" keycode="VK_PAGE_DOWN" command="cmd_scrollPageDown"/>
<handler event="keypress" keycode="VK_HOME" command="cmd_scrollTop" />
<handler event="keypress" keycode="VK_END" command="cmd_scrollBottom" />
<handler event="keypress" keycode="VK_LEFT" modifiers="alt" command="cmd_moveLeft2" />
<handler event="keypress" keycode="VK_RIGHT" modifiers="alt" command="cmd_moveRight2" />
<handler event="keypress" keycode="VK_LEFT" modifiers="alt,shift" command="cmd_selectLeft2" />
<handler event="keypress" keycode="VK_RIGHT" modifiers="alt,shift" command="cmd_selectRight2" />
<handler event="keypress" keycode="VK_LEFT" modifiers="shift" command="cmd_selectLeft" />
<handler event="keypress" keycode="VK_RIGHT" modifiers="shift" command="cmd_selectRight" />
<handler event="keypress" keycode="VK_UP" modifiers="alt,shift" command="cmd_selectUp2" />
<handler event="keypress" keycode="VK_DOWN" modifiers="alt,shift" command="cmd_selectDown2" />
<handler event="keypress" keycode="VK_UP" modifiers="shift" command="cmd_selectUp" />
<handler event="keypress" keycode="VK_DOWN" modifiers="shift" command="cmd_selectDown" />
<handler event="keypress" keycode="VK_UP" modifiers="accel" command="cmd_moveUp2"/>
<handler event="keypress" keycode="VK_DOWN" modifiers="accel" command="cmd_moveDown2"/>
</handlers>
</binding>
<binding id="editor">
<handlers>
<handler event="keypress" key=" " modifiers="shift" command="cmd_scrollPageUp" />
<handler event="keypress" key=" " command="cmd_scrollPageDown" />
<handler event="keypress" key="z" command="cmd_undo" modifiers="accel"/>
<handler event="keypress" key="z" command="cmd_redo" modifiers="accel,shift" />
<handler event="keypress" key="x" command="cmd_cut" modifiers="accel"/>
<handler event="keypress" key="c" command="cmd_copy" modifiers="accel"/>
<handler event="keypress" key="v" command="cmd_paste" modifiers="accel"/>
<handler event="keypress" key="v" command="cmd_pasteNoFormatting" modifiers="accel,shift"/>
<handler event="keypress" key="a" command="cmd_selectAll" modifiers="accel"/>
<handler event="keypress" key="v" command="cmd_pasteNoFormatting" modifiers="accel,alt,shift"/>
</handlers>
</binding>
</bindings>

View file

@ -5,8 +5,6 @@
if CONFIG['OS_ARCH'] == 'WINNT':
DIRS += ['win']
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
DIRS += ['mac']
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
DIRS += ['android']
elif CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'):