私はかなり厄介な技術的な問題を抱えており、Webkitの専門家が周りにいることを望んでいます。私はクライアント用のiOSアプリケーションに取り組んでいます。ほとんどのアプリケーションは、UIWebViewコントローラーで提供されるHTML5コンテンツです。
約1週間前、QAチームはアプリケーションがクラッシュしたことを報告し始めました。先週、1日に約1件のクラッシュレポートを受け取りました。残念ながら、これらは一種のクラッシュであり、クラッシュを一貫して再現する明確な一連の手順を決定することはできません。不思議なことに、これらのクラッシュレポートの一部は、iOSコードベースの古いバージョンを使用しています。このコードは、このクラッシュの動作に誰も気付かずに数か月間正常に実行されます。
しかし、すべてのクラッシュ状況に共通しているのは、最新バージョンのHTMLWebアプリページを提供する更新されたバックエンドに対してすべてが実行されていることです。つまり、かなりのことですが、サーバー側で何か新しいことを行ったようです。これにより、iOSコードの何かがクラッシュします。
クラッシュログはかなり一貫しています。シンボリックログは次のとおりです。
0 WebCore 0x33147ab0 WebCore::FrameLoader::cancelledError(WebCore::ResourceRequest const&) const + 4
1 WebCore 0x33070fbe WebCore::ResourceLoader::init(WebCore::ResourceRequest const&) + 166
2 WebCore 0x33070e66 WebCore::SubresourceLoader::startLoading() + 14
3 WebCore 0x33070c4e WebCore::ResourceLoadScheduler::servePendingRequests(WebCore::ResourceLoadScheduler::HostInformation*, WebCore::ResourceLoadPriority) + 46
4 WebCore 0x33076508 WebCore::ResourceLoadScheduler::servePendingRequests(WebCore::ResourceLoadPriority) + 36
5 WebCore 0x32fd38c8 WebCore::ThreadTimers::sharedTimerFiredInternal() + 92
(WebCoreでのクラッシュについて説明するほとんどの質問には、deallocメソッドでwebview.delegateをnilに設定するという提案があります。これは、私たちの問題ではないようです)。
今、私は1つの理論を持っています(これについては後で説明します)が、私が持っていないのは明確な証拠です。そこで、webkit.orgからソースを取得し、WebKitがクラッシュしたときに何をしていたかを理解するために十分に読み込もうとしています。iOSデバイスとまったく同じバージョンのWebKitソースを使用しているとは思いません(これは5.0.1および5.1.1デバイスで見られます)。主要なメソッドはダウンロードリソースを参照しているようです( CSSと画像)が、nullのURLが関係しているように見えるため、cancelledErrorメソッドを呼び出すことになります。
次に、FrameLoaderはこれを行います。
ResourceError FrameLoader::cancelledError(const ResourceRequest& request) const
{
ResourceError error = m_client->cancelledError(request);
error.setIsCancellation(true);
return error;
}
このメソッドでアプリがクラッシュするのは次のとおりです。
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000008
これは、m_clientが有効なものを指していないことを示唆しています。
今、私は、腸の感触と状況証拠に基づいて、何が起こっているのかについての理論を持っています。
UIWebViewには、WebビューにロードされているURLを評価するデリゲートがあります。特定の状況では、次のように、別のViewControllerで新しいURLを起動することにします。
- (BOOL)webView:(UIWebView *)source shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
...
if ([self.popupStrategy shouldPopupURL:[request URL] fromCurrent:[source.request URL]]) {
PopupTransitionViewController *popController = [self createPopupController:request];
... push it onto the navigation controller ...
}
...
}
このポップアップ戦略がtrueを返す原因となる重要な条件の1つは、クロスドメインリンク中に発生します。つまり、ユーザーがリンク/アイコンをタップし、そのリンクのターゲットがサードパーティのサイトによってホストされている場合、アプリは別のViewControllerで新しいコンテンツを起動します(さまざまな理由で、クロスドメインリンクでの優れたネイティブ遷移)。
数週間前に発生したサーバー側の変更の1つは、リンクhrefが更新されたことです。リンクはメインサーバーを呼び出し、メインサーバーはHTTPリダイレクトを送り返し、クライアントをサードパーティのサイトに送信します。
この場合、popupStrategyが2回呼び出されることがわかります。1回目はメインサーバーへのURLを評価し、2回目はサードパーティのURLを評価します。2番目のケースでは、ストラテジーはUIWebViewにリクエストを新しいViewControllerにロードするように指示します。私の考えでは、Webkitコードの何かが常にそれを好むとは限らず、タイミングなどの奇妙なことによって、これはある時点でクラッシュにつながる可能性があります。
この理論は、以前はサーバーコードベースに存在しなかった新しいWeb読み込み動作に基づいているため、私に固執します。これは、症状に便利に適合します。私がWebkitコードを読んだところ、参照されているメソッドの中には、クロスオリジンリクエストを検出したときにWebkitが特別な処理を行っているように見えるものがあります。しかし、クラッシュをキューで再現することは不可能だったので、これ以上続けることはありません。しかし、理論が真実であれば、私は合理的な修正を知っています。
私の希望は、誰かがWebkitの内部にある程度精通していて、次のことを提案できることです。
a)この理論はWebkitスタックトレースによってどの程度サポートされていますか?
b)私が取得しているスタックトレースによって示唆されている、他の誰かが見ることができる洞察はありますか?