From b76f70a9e699f80807ef5fff58281fe5aa15da17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Katzer?= Date: Tue, 17 Jan 2017 14:02:16 +0100 Subject: [PATCH] Make it work with WKWebView #198 --- plugin.xml | 46 +++------------- src/ios/APPBackgroundMode.h | 30 +++++----- src/ios/APPBackgroundMode.m | 76 ++++++++++++++++++++------ src/ios/APPMethodMagic.h | 93 +++++++++++++++++++++++++++++++ src/ios/APPMethodMagic.m | 106 ++++++++++++++++++++++++++++++++++++ 5 files changed, 283 insertions(+), 68 deletions(-) create mode 100644 src/ios/APPMethodMagic.h create mode 100644 src/ios/APPMethodMagic.m diff --git a/plugin.xml b/plugin.xml index e988696..a21a4c2 100644 --- a/plugin.xml +++ b/plugin.xml @@ -40,7 +40,6 @@ - audio @@ -51,6 +50,8 @@ + + @@ -67,11 +68,6 @@ - @@ -86,43 +82,19 @@ - - - + + - - + + - - - - - - - - - - - - + + + - - - - - - - - - - - - - - diff --git a/src/ios/APPBackgroundMode.h b/src/ios/APPBackgroundMode.h index 0aef2a0..54da95c 100644 --- a/src/ios/APPBackgroundMode.h +++ b/src/ios/APPBackgroundMode.h @@ -1,22 +1,22 @@ /* - Copyright 2013-2017 appPlant GmbH + Copyright 2013-2017 appPlant GmbH - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. */ #import diff --git a/src/ios/APPBackgroundMode.m b/src/ios/APPBackgroundMode.m index 50cae17..dae1cad 100644 --- a/src/ios/APPBackgroundMode.m +++ b/src/ios/APPBackgroundMode.m @@ -1,35 +1,50 @@ /* - Copyright 2013-2017 appPlant GmbH + Copyright 2013-2017 appPlant GmbH - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. */ +#import "APPMethodMagic.h" #import "APPBackgroundMode.h" +#import @implementation APPBackgroundMode +#pragma mark - +#pragma mark Constants + NSString* const kAPPBackgroundJsNamespace = @"cordova.plugins.backgroundMode"; NSString* const kAPPBackgroundEventActivate = @"activate"; NSString* const kAPPBackgroundEventDeactivate = @"deactivate"; NSString* const kAPPBackgroundEventFailure = @"failure"; + #pragma mark - -#pragma mark Initialization +#pragma mark Life Cycle + +/** + * Called by runtime once the Class has been loaded. + * Exchange method implementations to hook into their execution. + */ ++ (void) load +{ + [self swizzleWKWebViewEngine]; +} /** * Initialize the plugin. @@ -208,4 +223,33 @@ NSString* const kAPPBackgroundEventFailure = @"failure"; [self.commandDelegate evalJs:js]; } +#pragma mark - +#pragma mark Swizzling + +/** + * Swizzle some implementations of CDVWKWebViewEngine. + */ ++ (void) swizzleWKWebViewEngine +{ + if (!IsAtLeastiOSVersion(@"8.0")) + return; + + Class wkWebViewEngineCls = NSClassFromString(@"CDVWKWebViewEngine"); + SEL selector = NSSelectorFromString(@"createConfigurationFromSettings:"); + + if (!wkWebViewEngineCls) + return; + + SwizzleSelectorWithBlock_Begin(wkWebViewEngineCls, selector) + ^(CDVPlugin *self, NSDictionary *settings) { + id obj = ((id (*)(id, SEL, NSDictionary*))_imp)(self, _cmd, settings); + + SEL sel = NSSelectorFromString(@"_setAlwaysRunsAtForegroundPriority:"); + ((void (*)(id, SEL, BOOL))[obj methodForSelector:selector])(obj, sel, YES); + + return sel; + } + SwizzleSelectorWithBlock_End; +} + @end diff --git a/src/ios/APPMethodMagic.h b/src/ios/APPMethodMagic.h new file mode 100644 index 0000000..84de791 --- /dev/null +++ b/src/ios/APPMethodMagic.h @@ -0,0 +1,93 @@ +/* + Copyright 2013-2017 appPlant GmbH + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +/** + * Code extracted from + * - http://defagos.github.io/yet_another_article_about_method_swizzling/ + * - https://gist.github.com/defagos/1312fec96b48540efa5c + */ + +#import +#import + +#define SwizzleSelector(clazz, selector, newImpl, oldImpl) \ +(*oldImpl) = (__typeof((*oldImpl)))class_swizzleSelector((clazz), (selector), (IMP)(newImpl)) + +#define SwizzleClassSelector(clazz, selector, newImpl, oldImpl) \ +(*oldImpl) = (__typeof((*oldImpl)))class_swizzleClassSelector((clazz), (selector), (IMP)(newImpl)) + +#define SwizzleSelectorWithBlock_Begin(clazz, selector) { \ +SEL _cmd = selector; \ +__block IMP _imp = class_swizzleSelectorWithBlock((clazz), (selector), +#define SwizzleSelectorWithBlock_End );} + +#define SwizzleClassSelectorWithBlock_Begin(clazz, selector) { \ +SEL _cmd = selector; \ +__block IMP _imp = class_swizzleClassSelectorWithBlock((clazz), (selector), +#define SwizzleClassSelectorWithBlock_End );} + +/** + * Swizzle class method specified by class and selector + * through the provided method implementation. + * + * @param [ Class ] clazz The class containing the method. + * @param [ SEL ] selector The selector of the method. + * @param [ IMP ] newImpl The new implementation of the method. + * + * @return [ IMP ] The previous implementation of the method. + */ +IMP class_swizzleClassSelector(Class clazz, SEL selector, IMP newImpl); + +/** + * Swizzle class method specified by class and selector + * through the provided code block. + * + * @param [ Class ] clazz The class containing the method. + * @param [ SEL ] selector The selector of the method. + * @param [ id ] newImplBlock The new implementation of the method. + * + * @return [ IMP ] The previous implementation of the method. + */ +IMP class_swizzleClassSelectorWithBlock(Class clazz, SEL selector, id newImplBlock); + +/** + * Swizzle method specified by class and selector + * through the provided code block. + * + * @param [ Class ] clazz The class containing the method. + * @param [ SEL ] selector The selector of the method. + * @param [ id ] newImplBlock The new implementation of the method. + * + * @return [ IMP ] The previous implementation of the method. + */ +IMP class_swizzleSelectorWithBlock(Class clazz, SEL selector, id newImplBlock); + +/** + * Swizzle method specified by class and selector + * through the provided method implementation. + * + * @param [ Class ] clazz The class containing the method. + * @param [ SEL ] selector The selector of the method. + * @param [ IMP ] newImpl The new implementation of the method. + * + * @return [ IMP ] The previous implementation of the method. + */ +IMP class_swizzleSelector(Class clazz, SEL selector, IMP newImpl); diff --git a/src/ios/APPMethodMagic.m b/src/ios/APPMethodMagic.m new file mode 100644 index 0000000..3f3ee98 --- /dev/null +++ b/src/ios/APPMethodMagic.m @@ -0,0 +1,106 @@ +/* + Copyright 2013-2017 appPlant GmbH + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +/** + * Code extracted from + * - http://defagos.github.io/yet_another_article_about_method_swizzling/ + * - https://gist.github.com/defagos/1312fec96b48540efa5c + */ + +#import "APPMethodMagic.h" +#import +#import + +/** + * Swizzle class method specified by class and selector + * through the provided method implementation. + * + * @param [ Class ] clazz The class containing the method. + * @param [ SEL ] selector The selector of the method. + * @param [ IMP ] newImpl The new implementation of the method. + * + * @return [ IMP ] The previous implementation of the method. + */ +IMP class_swizzleClassSelector(Class clazz, SEL selector, IMP newImpl) +{ + return class_swizzleSelector(object_getClass(clazz), selector, newImpl); +} + +/** + * Swizzle class method specified by class and selector + * through the provided code block. + * + * @param [ Class ] clazz The class containing the method. + * @param [ SEL ] selector The selector of the method. + * @param [ id ] newImplBlock The new implementation of the method. + * + * @return [ IMP ] The previous implementation of the method. + */ +IMP class_swizzleClassSelectorWithBlock(Class clazz, SEL selector, id newImplBlock) +{ + IMP newImpl = imp_implementationWithBlock(newImplBlock); + return class_swizzleClassSelector(clazz, selector, newImpl); +} + +/** + * Swizzle method specified by class and selector + * through the provided code block. + * + * @param [ Class ] clazz The class containing the method. + * @param [ SEL ] selector The selector of the method. + * @param [ id ] newImplBlock The new implementation of the method. + * + * @return [ IMP ] The previous implementation of the method. + */ +IMP class_swizzleSelectorWithBlock(Class clazz, SEL selector, id newImplBlock) +{ + IMP newImpl = imp_implementationWithBlock(newImplBlock); + return class_swizzleSelector(clazz, selector, newImpl); +} + +/** + * Swizzle method specified by class and selector + * through the provided method implementation. + * + * @param [ Class ] clazz The class containing the method. + * @param [ SEL ] selector The selector of the method. + * @param [ IMP ] newImpl The new implementation of the method. + * + * @return [ IMP ] The previous implementation of the method. + */ +IMP class_swizzleSelector(Class clazz, SEL selector, IMP newImpl) +{ + Method method = class_getInstanceMethod(clazz, selector); + const char *types = method_getTypeEncoding(method); + + class_addMethod(clazz, selector, imp_implementationWithBlock(^(__unsafe_unretained id self, va_list argp) { + struct objc_super super = { + .receiver = self, + .super_class = class_getSuperclass(clazz) + }; + + id (*objc_msgSendSuper_typed)(struct objc_super*, SEL, va_list) = (void*)&objc_msgSendSuper; + return objc_msgSendSuper_typed(&super, selector, argp); + }), types); + + return class_replaceMethod(clazz, selector, newImpl, types); +} +